[automerger skipped] Remove READ_SMS permission for ACTION_SMS_MMS_DB_CREATED am: 109c42f36d -s ours
am skip reason: Change-Id I3bfad759d3a440685e8fb89e8f0978da00f7c654 with SHA-1 dd0e743c88 is in history
Change-Id: I390b372cfa6c98adc44a57edf2ab5346f1bacb2f
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3b95bce..dbd5436 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -107,12 +107,6 @@
android:multiprocess="false"
android:writePermission="android.permission.MODIFY_PHONE_STATE" />
- <provider android:name="CellBroadcastProvider"
- android:authorities="cellbroadcasts_fwk"
- android:exported="true"
- android:singleUser="true"
- android:multiprocess="false" />
-
<provider android:name="HbpcdLookupProvider"
android:authorities="hbpcd_lookup"
android:exported="true"
@@ -126,12 +120,6 @@
android:singleUser="true"
android:multiprocess="false" />
- <provider android:name="RcsProvider"
- android:authorities="rcs"
- android:multiprocess="false"
- android:exported="false"
- android:singleUser="true" />
-
<service
android:name=".TelephonyBackupAgent$DeferredSmsMmsRestoreService"
android:exported="false" />
diff --git a/OWNERS b/OWNERS
index 92458db..bce6270 100644
--- a/OWNERS
+++ b/OWNERS
@@ -10,3 +10,4 @@
tgunn@google.com
breadley@google.com
nazaninb@google.com
+sarahchin@google.com
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..d287f23
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,15 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsTelephonyProviderTestCases"
+ },
+ {
+ "name": "TeleServiceTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/assets/carrier_list.pb b/assets/carrier_list.pb
index 3519d2c..c23d371 100644
--- a/assets/carrier_list.pb
+++ b/assets/carrier_list.pb
Binary files differ
diff --git a/assets/carrier_list.textpb b/assets/carrier_list.textpb
index b1c6825..8439b87 100644
--- a/assets/carrier_list.textpb
+++ b/assets/carrier_list.textpb
Binary files differ
diff --git a/assets/sdk28_carrier_id/carrier_list.pb b/assets/sdk28_carrier_id/carrier_list.pb
index 856c5bc..700eb89 100644
--- a/assets/sdk28_carrier_id/carrier_list.pb
+++ b/assets/sdk28_carrier_id/carrier_list.pb
Binary files differ
diff --git a/assets/sdk28_carrier_id/carrier_list.textpb b/assets/sdk28_carrier_id/carrier_list.textpb
index 23196a5..619d989 100644
--- a/assets/sdk28_carrier_id/carrier_list.textpb
+++ b/assets/sdk28_carrier_id/carrier_list.textpb
Binary files differ
diff --git a/assets/sdk29_carrier_id/carrier_list.pb b/assets/sdk29_carrier_id/carrier_list.pb
new file mode 100644
index 0000000..3519d2c
--- /dev/null
+++ b/assets/sdk29_carrier_id/carrier_list.pb
Binary files differ
diff --git a/assets/sdk29_carrier_id/carrier_list.textpb b/assets/sdk29_carrier_id/carrier_list.textpb
new file mode 100644
index 0000000..b1c6825
--- /dev/null
+++ b/assets/sdk29_carrier_id/carrier_list.textpb
Binary files differ
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index f3baf24..6cfcdfb 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" product="tablet" msgid="9194799012395299737">"Configuration du réseau mobile"</string>
- <string name="app_label" product="default" msgid="8338087656149558019">"Téléphone et stockage des messages"</string>
+ <string name="app_label" product="default" msgid="8338087656149558019">"Stockage tél. et SMS/MMS"</string>
</resources>
diff --git a/src/com/android/providers/telephony/CellBroadcastProvider.java b/src/com/android/providers/telephony/CellBroadcastProvider.java
deleted file mode 100644
index 4c8a7e2..0000000
--- a/src/com/android/providers/telephony/CellBroadcastProvider.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-package com.android.providers.telephony;
-
-import android.app.AppOpsManager;
-import android.content.ContentProvider;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.UriMatcher;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Process;
-import android.provider.Telephony.CellBroadcasts;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Arrays;
-
-/**
- * The content provider that provides access of cell broadcast message to application.
- * Permission {@link android.permission.READ_CELL_BROADCASTS} is required for querying the cell
- * broadcast message. Only phone process has the permission to write/update the database via this
- * provider.
- */
-public class CellBroadcastProvider extends ContentProvider {
- /** Interface for read/write permission check. */
- public interface PermissionChecker {
- /** Return {@code True} if the caller has the permission to write/update the database. */
- boolean hasWritePermission();
-
- /** Return {@code True} if the caller has the permission to query the database. */
- boolean hasReadPermission();
- }
-
- private static final String TAG = CellBroadcastProvider.class.getSimpleName();
-
- private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
-
- /** Database name. */
- private static final String DATABASE_NAME = "cellbroadcasts.db";
-
- /** Database version. */
- private static final int DATABASE_VERSION = 1;
-
- /** URI matcher for ContentProvider queries. */
- private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
-
- /** URI matcher type to get all cell broadcasts. */
- private static final int ALL = 0;
-
- /** MIME type for the list of all cell broadcasts. */
- private static final String LIST_TYPE = "vnd.android.cursor.dir/cellbroadcast";
-
- /** Table name of cell broadcast message. */
- @VisibleForTesting
- public static final String CELL_BROADCASTS_TABLE_NAME = "cell_broadcasts";
-
- /** Authority string for content URIs. */
- @VisibleForTesting
- public static final String AUTHORITY = "cellbroadcasts_fwk";
-
- /** Content uri of this provider. */
- public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts_fwk");
-
- @VisibleForTesting
- public PermissionChecker mPermissionChecker;
-
- /** The database helper for this content provider. */
- @VisibleForTesting
- public SQLiteOpenHelper mDbHelper;
-
- static {
- sUriMatcher.addURI(AUTHORITY, null, ALL);
- }
-
- public CellBroadcastProvider() {}
-
- @VisibleForTesting
- public CellBroadcastProvider(PermissionChecker permissionChecker) {
- mPermissionChecker = permissionChecker;
- }
-
- @Override
- public boolean onCreate() {
- mDbHelper = new CellBroadcastDatabaseHelper(getContext());
- mPermissionChecker = new CellBroadcastPermissionChecker();
- setAppOps(AppOpsManager.OP_READ_CELL_BROADCASTS, AppOpsManager.OP_NONE);
- return true;
- }
-
- /**
- * Return the MIME type of the data at the specified URI.
- *
- * @param uri the URI to query.
- * @return a MIME type string, or null if there is no type.
- */
- @Override
- public String getType(Uri uri) {
- int match = sUriMatcher.match(uri);
- switch (match) {
- case ALL:
- return LIST_TYPE;
- default:
- return null;
- }
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- checkReadPermission();
-
- if (DBG) {
- Log.d(TAG, "query:"
- + " uri = " + uri
- + " projection = " + Arrays.toString(projection)
- + " selection = " + selection
- + " selectionArgs = " + Arrays.toString(selectionArgs)
- + " sortOrder = " + sortOrder);
- }
-
- String orderBy;
- if (!TextUtils.isEmpty(sortOrder)) {
- orderBy = sortOrder;
- } else {
- orderBy = CellBroadcasts.RECEIVED_TIME + " DESC";
- }
-
- int match = sUriMatcher.match(uri);
- switch (match) {
- case ALL:
- return getReadableDatabase().query(
- CELL_BROADCASTS_TABLE_NAME, projection, selection, selectionArgs,
- null /* groupBy */, null /* having */, orderBy);
- default:
- throw new IllegalArgumentException(
- "Query method doesn't support this uri = " + uri);
- }
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- checkWritePermission();
-
- if (DBG) {
- Log.d(TAG, "insert:"
- + " uri = " + uri
- + " contentValue = " + values);
- }
-
- switch (sUriMatcher.match(uri)) {
- case ALL:
- long row = getWritableDatabase().insertOrThrow(CELL_BROADCASTS_TABLE_NAME, null,
- values);
- if (row > 0) {
- Uri newUri = ContentUris.withAppendedId(CONTENT_URI, row);
- getContext().getContentResolver()
- .notifyChange(CONTENT_URI, null /* observer */);
- return newUri;
- } else {
- Log.e(TAG, "Insert record failed because of unknown reason, uri = " + uri);
- return null;
- }
- default:
- throw new IllegalArgumentException(
- "Insert method doesn't support this uri = " + uri);
- }
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- checkWritePermission();
-
- if (DBG) {
- Log.d(TAG, "delete:"
- + " uri = " + uri
- + " selection = " + selection
- + " selectionArgs = " + Arrays.toString(selectionArgs));
- }
-
- switch (sUriMatcher.match(uri)) {
- case ALL:
- return getWritableDatabase().delete(CELL_BROADCASTS_TABLE_NAME,
- selection, selectionArgs);
- default:
- throw new IllegalArgumentException(
- "Delete method doesn't support this uri = " + uri);
- }
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- checkWritePermission();
-
- if (DBG) {
- Log.d(TAG, "update:"
- + " uri = " + uri
- + " values = {" + values + "}"
- + " selection = " + selection
- + " selectionArgs = " + Arrays.toString(selectionArgs));
- }
-
- switch (sUriMatcher.match(uri)) {
- case ALL:
- int rowCount = getWritableDatabase().update(
- CELL_BROADCASTS_TABLE_NAME,
- values,
- selection,
- selectionArgs);
- if (rowCount > 0) {
- getContext().getContentResolver().notifyChange(uri, null /* observer */);
- }
- return rowCount;
- default:
- throw new IllegalArgumentException(
- "Update method doesn't support this uri = " + uri);
- }
- }
-
- @VisibleForTesting
- public static String getStringForCellBroadcastTableCreation(String tableName) {
- return "CREATE TABLE " + tableName + " ("
- + CellBroadcasts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
- + CellBroadcasts.SUB_ID + " INTEGER,"
- + CellBroadcasts.GEOGRAPHICAL_SCOPE + " INTEGER,"
- + CellBroadcasts.PLMN + " TEXT,"
- + CellBroadcasts.LAC + " INTEGER,"
- + CellBroadcasts.CID + " INTEGER,"
- + CellBroadcasts.SERIAL_NUMBER + " INTEGER,"
- + CellBroadcasts.SERVICE_CATEGORY + " INTEGER,"
- + CellBroadcasts.LANGUAGE_CODE + " TEXT,"
- + CellBroadcasts.MESSAGE_BODY + " TEXT,"
- + CellBroadcasts.MESSAGE_FORMAT + " INTEGER,"
- + CellBroadcasts.MESSAGE_PRIORITY + " INTEGER,"
- + CellBroadcasts.ETWS_WARNING_TYPE + " INTEGER,"
- + CellBroadcasts.CMAS_MESSAGE_CLASS + " INTEGER,"
- + CellBroadcasts.CMAS_CATEGORY + " INTEGER,"
- + CellBroadcasts.CMAS_RESPONSE_TYPE + " INTEGER,"
- + CellBroadcasts.CMAS_SEVERITY + " INTEGER,"
- + CellBroadcasts.CMAS_URGENCY + " INTEGER,"
- + CellBroadcasts.CMAS_CERTAINTY + " INTEGER,"
- + CellBroadcasts.RECEIVED_TIME + " BIGINT,"
- + CellBroadcasts.MESSAGE_BROADCASTED + " BOOLEAN DEFAULT 0,"
- + CellBroadcasts.GEOMETRIES + " TEXT,"
- + CellBroadcasts.MAXIMUM_WAIT_TIME + " INTEGER);";
- }
-
- private SQLiteDatabase getWritableDatabase() {
- return mDbHelper.getWritableDatabase();
- }
-
- private SQLiteDatabase getReadableDatabase() {
- return mDbHelper.getReadableDatabase();
- }
-
- private void checkWritePermission() {
- if (!mPermissionChecker.hasWritePermission()) {
- throw new SecurityException(
- "No permission to write CellBroadcast provider");
- }
- }
-
- private void checkReadPermission() {
- if (!mPermissionChecker.hasReadPermission()) {
- throw new SecurityException(
- "No permission to read CellBroadcast provider");
- }
- }
-
- private class CellBroadcastDatabaseHelper extends SQLiteOpenHelper {
- CellBroadcastDatabaseHelper(Context context) {
- super(context, DATABASE_NAME, null /* factory */, DATABASE_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL(getStringForCellBroadcastTableCreation(CELL_BROADCASTS_TABLE_NAME));
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
- }
-
- private class CellBroadcastPermissionChecker implements PermissionChecker {
- @Override
- public boolean hasWritePermission() {
- // Only the phone process has the write permission to modify this provider.
- return Binder.getCallingUid() == Process.PHONE_UID;
- }
-
- @Override
- public boolean hasReadPermission() {
- // Only the phone process has the read permission to query data from this provider.
- return Binder.getCallingUid() == Process.PHONE_UID;
- }
- }
-}
diff --git a/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java b/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java
index 0149687..056738f 100644
--- a/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java
+++ b/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java
@@ -65,7 +65,6 @@
import android.database.sqlite.SQLiteQueryBuilder;
import android.util.Log;
import android.util.Xml;
-import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -79,6 +78,7 @@
import com.android.internal.telephony.HbpcdLookup.MccSidRange;
import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch;
import com.android.internal.telephony.HbpcdLookup.NanpAreaCode;
+import com.android.internal.util.XmlUtils;
public class HbpcdLookupDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "HbpcdLockupDatabaseHelper";
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
index 7ecfc46..d5aa308 100644
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
@@ -17,6 +17,7 @@
package com.android.providers.telephony;
import static android.provider.Telephony.RcsColumns.IS_RCS_TABLE_SCHEMA_CODE_COMPLETE;
+import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
@@ -49,7 +50,6 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.PhoneFactory;
import com.google.android.mms.pdu.EncodedStringValue;
import com.google.android.mms.pdu.PduHeaders;
@@ -294,11 +294,6 @@
// Memory optimization - close idle connections after 30s of inactivity
setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
setWriteAheadLoggingEnabled(false);
- try {
- PhoneFactory.addLocalLog(TAG, 100);
- } catch (IllegalArgumentException e) {
- // ignore
- }
}
private static synchronized MmsSmsDatabaseErrorHandler getDbErrorHandler(Context context) {
@@ -550,14 +545,6 @@
createMmsTables(db);
createSmsTables(db);
createCommonTables(db);
-
- if (IS_RCS_TABLE_SCHEMA_CODE_COMPLETE) {
- RcsProviderThreadHelper.createThreadTables(db);
- RcsProviderParticipantHelper.createParticipantTables(db);
- RcsProviderMessageHelper.createRcsMessageTables(db);
- RcsProviderEventHelper.createRcsEventTables(db);
- }
-
createCommonTriggers(db);
createMmsTriggers(db);
createWordsTables(db);
@@ -566,12 +553,10 @@
private static void localLog(String logMsg) {
Log.d(TAG, logMsg);
- PhoneFactory.localLog(TAG, logMsg);
}
private static void localLogWtf(String logMsg) {
Slog.wtf(TAG, logMsg);
- PhoneFactory.localLog(TAG, logMsg);
}
private boolean isInitialCreateDone() {
@@ -1012,7 +997,7 @@
"service_center TEXT," +
"locked INTEGER DEFAULT 0," +
"sub_id INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " +
- "error_code INTEGER DEFAULT 0," +
+ "error_code INTEGER DEFAULT " + NO_ERROR_CODE + ", " +
"creator TEXT," +
"seen INTEGER DEFAULT 0" +
");";
@@ -1665,15 +1650,6 @@
db.endTransaction();
}
// fall through
- case 67:
- if (currentVersion <= 67 || !IS_RCS_TABLE_SCHEMA_CODE_COMPLETE) {
- return;
- }
- RcsProviderThreadHelper.createThreadTables(db);
- RcsProviderParticipantHelper.createParticipantTables(db);
- RcsProviderMessageHelper.createRcsMessageTables(db);
- RcsProviderEventHelper.createRcsEventTables(db);
- return;
}
Log.e(TAG, "Destroying all old data.");
@@ -1816,7 +1792,7 @@
private void upgradeDatabaseToVersion48(SQLiteDatabase db) {
// Add 'error_code' column to sms table.
- db.execSQL("ALTER TABLE sms ADD COLUMN error_code INTEGER DEFAULT 0");
+ db.execSQL("ALTER TABLE sms ADD COLUMN error_code INTEGER DEFAULT " + NO_ERROR_CODE);
}
private void upgradeDatabaseToVersion51(SQLiteDatabase db) {
diff --git a/src/com/android/providers/telephony/MmsSmsProvider.java b/src/com/android/providers/telephony/MmsSmsProvider.java
index 8c3555c..1170aad 100644
--- a/src/com/android/providers/telephony/MmsSmsProvider.java
+++ b/src/com/android/providers/telephony/MmsSmsProvider.java
@@ -305,6 +305,7 @@
private SQLiteOpenHelper mOpenHelper;
private boolean mUseStrictPhoneNumberComparation;
+ private int mMinMatch;
private static final String METHOD_IS_RESTORING = "is_restoring";
private static final String IS_RESTORING_KEY = "restoring";
@@ -316,6 +317,9 @@
mUseStrictPhoneNumberComparation =
getContext().getResources().getBoolean(
com.android.internal.R.bool.config_use_strict_phone_number_comparation);
+ mMinMatch =
+ getContext().getResources().getInteger(
+ com.android.internal.R.integer.config_phonenumber_compare_min_match);
TelephonyBackupAgent.DeferredSmsMmsRestoreService.startIfFilesExist(getContext());
return true;
}
@@ -542,7 +546,7 @@
selectionArgs = new String[] { refinedAddress };
} else {
selection += " OR PHONE_NUMBERS_EQUAL(address, ?, " +
- (mUseStrictPhoneNumberComparation ? 1 : 0) + ")";
+ (mUseStrictPhoneNumberComparation ? "1)" : "0, " + mMinMatch + ")");
selectionArgs = new String[] { refinedAddress, refinedAddress };
}
@@ -997,13 +1001,14 @@
* FROM pdu, (SELECT msg_id AS address_msg_id
* FROM addr
* WHERE (address='<phoneNumber>' OR
- * PHONE_NUMBERS_EQUAL(addr.address, '<phoneNumber>', 1/0)))
+ * PHONE_NUMBERS_EQUAL(addr.address, '<phoneNumber>', 1/0, none/mMinMatch)))
* AS matching_addresses
* WHERE pdu._id = matching_addresses.address_msg_id
* UNION
* SELECT ...
* FROM sms
- * WHERE (address='<phoneNumber>' OR PHONE_NUMBERS_EQUAL(sms.address, '<phoneNumber>', 1/0));
+ * WHERE (address='<phoneNumber>' OR
+ * PHONE_NUMBERS_EQUAL(sms.address, '<phoneNumber>', 1/0, none/mMinMatch));
*/
private Cursor getMessagesByPhoneNumber(
String phoneNumber, String[] projection, String selection,
@@ -1018,7 +1023,7 @@
selection,
"(address=" + escapedPhoneNumber + " OR PHONE_NUMBERS_EQUAL(address, " +
escapedPhoneNumber +
- (mUseStrictPhoneNumberComparation ? ", 1))" : ", 0))"));
+ (mUseStrictPhoneNumberComparation ? ", 1))" : ", 0, " + mMinMatch + "))"));
SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();
@@ -1030,7 +1035,7 @@
"FROM addr WHERE (address=" + escapedPhoneNumber +
" OR PHONE_NUMBERS_EQUAL(addr.address, " +
escapedPhoneNumber +
- (mUseStrictPhoneNumberComparation ? ", 1))) " : ", 0))) ") +
+ (mUseStrictPhoneNumberComparation ? ", 1))) " : ", 0, " + mMinMatch + "))) ") +
"AS matching_addresses");
smsQueryBuilder.setTables(smsTable);
diff --git a/src/com/android/providers/telephony/RcsProvider.java b/src/com/android/providers/telephony/RcsProvider.java
deleted file mode 100644
index 3235b27..0000000
--- a/src/com/android/providers/telephony/RcsProvider.java
+++ /dev/null
@@ -1,804 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_URI_PART;
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-
-import static com.android.providers.telephony.RcsProviderUtil.buildUriWithRowIdAppended;
-import static com.android.providers.telephony.RcsProviderUtil.returnUriAsIsIfSuccessful;
-
-import android.app.AppOpsManager;
-import android.content.ContentProvider;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.UriMatcher;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Content provider to handle RCS messages. The functionality here is similar to SmsProvider,
- * MmsProvider etc.
- *
- * The provider has constraints around inserting, updating and deleting - the user needs to know
- * whether they are inserting a message that is incoming/outgoing, or the thread they are inserting
- * is a group or p2p etc. This is in order to keep the implementation simple and avoid complex
- * queries.
- *
- * @hide
- */
-public class RcsProvider extends ContentProvider {
- static final String TAG = "RcsProvider";
- static final String AUTHORITY = "rcs";
- private static final String CONTENT_AUTHORITY = "content://" + AUTHORITY;
-
- private static final Uri PARTICIPANT_URI_PREFIX =
- Uri.parse(CONTENT_AUTHORITY + "/participant/");
- private static final Uri P2P_THREAD_URI_PREFIX = Uri.parse(CONTENT_AUTHORITY + "/p2p_thread/");
- private static final Uri FILE_TRANSFER_PREFIX = Uri.parse(
- CONTENT_AUTHORITY + "/file_transfer/");
- static final Uri GROUP_THREAD_URI_PREFIX = Uri.parse(CONTENT_AUTHORITY + "/group_thread/");
-
- // Rcs table names
- static final String RCS_THREAD_TABLE = "rcs_thread";
- static final String RCS_1_TO_1_THREAD_TABLE = "rcs_1_to_1_thread";
- static final String RCS_GROUP_THREAD_TABLE = "rcs_group_thread";
- static final String UNIFIED_RCS_THREAD_VIEW = "rcs_unified_rcs_thread_view";
- static final String RCS_PARTICIPANT_TABLE = "rcs_participant";
- static final String RCS_PARTICIPANT_THREAD_JUNCTION_TABLE = "rcs_thread_participant";
- static final String RCS_MESSAGE_TABLE = "rcs_message";
- static final String RCS_INCOMING_MESSAGE_TABLE = "rcs_incoming_message";
- static final String RCS_OUTGOING_MESSAGE_TABLE = "rcs_outgoing_message";
- static final String RCS_MESSAGE_DELIVERY_TABLE = "rcs_message_delivery";
- static final String UNIFIED_MESSAGE_VIEW = "rcs_unified_message_view";
- static final String RCS_FILE_TRANSFER_TABLE = "rcs_file_transfer";
- static final String RCS_THREAD_EVENT_TABLE = "rcs_thread_event";
- static final String RCS_PARTICIPANT_EVENT_TABLE = "rcs_participant_event";
- static final String RCS_UNIFIED_EVENT_VIEW = "rcs_unified_event_view";
-
- private static final UriMatcher URL_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
-
- private static final int UNIFIED_RCS_THREAD = 1;
- private static final int UNIFIED_RCS_THREAD_WITH_ID = 2;
- private static final int PARTICIPANT = 3;
- private static final int PARTICIPANT_WITH_ID = 4;
- private static final int PARTICIPANT_ALIAS_CHANGE_EVENT = 5;
- private static final int PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID = 6;
- private static final int P2P_THREAD = 7;
- private static final int P2P_THREAD_WITH_ID = 8;
- private static final int P2P_THREAD_PARTICIPANT = 9;
- private static final int P2P_THREAD_PARTICIPANT_WITH_ID = 10;
- private static final int GROUP_THREAD = 11;
- private static final int GROUP_THREAD_WITH_ID = 12;
- private static final int GROUP_THREAD_PARTICIPANT = 13;
- private static final int GROUP_THREAD_PARTICIPANT_WITH_ID = 14;
- private static final int GROUP_THREAD_PARTICIPANT_JOINED_EVENT = 15;
- private static final int GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID = 16;
- private static final int GROUP_THREAD_PARTICIPANT_LEFT_EVENT = 17;
- private static final int GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID = 18;
- private static final int GROUP_THREAD_NAME_CHANGE_EVENT = 19;
- private static final int GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID = 20;
- private static final int GROUP_THREAD_ICON_CHANGE_EVENT = 21;
- private static final int GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID = 22;
- private static final int UNIFIED_MESSAGE = 23;
- private static final int UNIFIED_MESSAGE_WITH_ID = 24;
- private static final int UNIFIED_MESSAGE_WITH_FILE_TRANSFER = 25;
- private static final int INCOMING_MESSAGE = 26;
- private static final int INCOMING_MESSAGE_WITH_ID = 27;
- private static final int OUTGOING_MESSAGE = 28;
- private static final int OUTGOING_MESSAGE_WITH_ID = 29;
- private static final int OUTGOING_MESSAGE_DELIVERY = 30;
- private static final int OUTGOING_MESSAGE_DELIVERY_WITH_ID = 31;
- private static final int UNIFIED_MESSAGE_ON_THREAD = 32;
- private static final int UNIFIED_MESSAGE_ON_THREAD_WITH_ID = 33;
- private static final int INCOMING_MESSAGE_ON_P2P_THREAD = 34;
- private static final int INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID = 35;
- private static final int OUTGOING_MESSAGE_ON_P2P_THREAD = 36;
- private static final int OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID = 37;
- private static final int INCOMING_MESSAGE_ON_GROUP_THREAD = 38;
- private static final int INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID = 39;
- private static final int OUTGOING_MESSAGE_ON_GROUP_THREAD = 40;
- private static final int OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID = 41;
- private static final int FILE_TRANSFER_WITH_ID = 42;
- private static final int EVENT = 43;
- private static final int CANONICAL_ADDRESS = 44;
-
- SQLiteOpenHelper mDbOpenHelper;
-
- @VisibleForTesting
- RcsProviderThreadHelper mThreadHelper;
- @VisibleForTesting
- RcsProviderParticipantHelper mParticipantHelper;
- @VisibleForTesting
- RcsProviderMessageHelper mMessageHelper;
- @VisibleForTesting
- RcsProviderEventHelper mEventHelper;
- @VisibleForTesting
- RcsProviderCanonicalAddressHelper mCanonicalAddressHelper;
-
- static {
- // example URI: content://rcs/thread
- URL_MATCHER.addURI(AUTHORITY, RCS_THREAD_URI_PART, UNIFIED_RCS_THREAD);
-
- // example URI: content://rcs/thread/4, where 4 is the thread id.
- URL_MATCHER.addURI(AUTHORITY, "thread/#", UNIFIED_RCS_THREAD_WITH_ID);
-
- // example URI: content://rcs/participant
- URL_MATCHER.addURI(AUTHORITY, "participant", PARTICIPANT);
-
- // example URI: content://rcs/participant/12, where 12 is the participant id
- URL_MATCHER.addURI(AUTHORITY, "participant/#", PARTICIPANT_WITH_ID);
-
- // example URI: content://rcs/participant/12/alias_change_event, where 12 is the participant
- // id.
- URL_MATCHER.addURI(AUTHORITY, "participant/#/alias_change_event",
- PARTICIPANT_ALIAS_CHANGE_EVENT);
-
- // example URI: content://rcs/participant/12/alias_change_event/4, where 12 is the
- // participant id, and 4 is the event id
- URL_MATCHER.addURI(AUTHORITY, "participant/#/alias_change_event/#",
- PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID);
-
- // example URI: content://rcs/p2p_thread
- URL_MATCHER.addURI(AUTHORITY, "p2p_thread", P2P_THREAD);
-
- // example URI: content://rcs/p2p_thread/4, where 4 is the thread id
- URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#", P2P_THREAD_WITH_ID);
-
- // example URI: content://rcs/p2p_thread/4/participant, where 4 is the thread id
- URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/participant", P2P_THREAD_PARTICIPANT);
-
- // example URI: content://rcs/p2p_thread/9/participant/3", only supports a 1 time insert.
- // 9 is the thread ID, 3 is the participant ID.
- URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/participant/#", P2P_THREAD_PARTICIPANT_WITH_ID);
-
- // example URI: content://rcs/group_thread
- URL_MATCHER.addURI(AUTHORITY, "group_thread", GROUP_THREAD);
-
- // example URI: content://rcs/group_thread/13, where 13 is the _id in rcs_threads table.
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#", GROUP_THREAD_WITH_ID);
-
- // example URI: content://rcs/group_thread/13/participant_joined_event. Supports
- // queries and inserts
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant_joined_event",
- GROUP_THREAD_PARTICIPANT_JOINED_EVENT);
-
- // example URI: content://rcs/group_thread/13/participant_joined_event/3. Supports deletes.
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant_joined_event/#",
- GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID);
-
- // example URI: content://rcs/group_thread/13/participant_left_event. Supports queries
- // and inserts
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant_left_event",
- GROUP_THREAD_PARTICIPANT_LEFT_EVENT);
-
- // example URI: content://rcs/group_thread/13/participant_left_event/5. Supports deletes
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant_left_event/#",
- GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID);
-
- // example URI: content://rcs/group_thread/13/name_changed_event. Supports queries and
- // inserts
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/name_changed_event",
- GROUP_THREAD_NAME_CHANGE_EVENT);
-
- // example URI: content://rcs/group_thread/13/name_changed_event/7. Supports deletes
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/name_changed_event/#",
- GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID);
-
- // example URI: content://rcs/group_thread/13/icon_changed_event. Supports queries and
- // inserts
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/icon_changed_event",
- GROUP_THREAD_ICON_CHANGE_EVENT);
-
- // example URI: content://rcs/group_thread/13/icon_changed_event/9. Supports deletes
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/icon_changed_event/#",
- GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID);
-
- // example URI: content://rcs/group_thread/18/participant
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant",
- GROUP_THREAD_PARTICIPANT);
-
- // example URI: content://rcs/group_thread/21/participant/4, only supports inserts and
- // deletes
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant/#",
- GROUP_THREAD_PARTICIPANT_WITH_ID);
-
- // example URI: content://rcs/message
- URL_MATCHER.addURI(AUTHORITY, "message", UNIFIED_MESSAGE);
-
- // example URI: content://rcs/message/4, where 4 is the message id.
- URL_MATCHER.addURI(AUTHORITY, "message/#", UNIFIED_MESSAGE_WITH_ID);
-
- // example URI: content://rcs/message/4/file_transfer, only supports inserts
- URL_MATCHER.addURI(AUTHORITY, "message/#/file_transfer",
- UNIFIED_MESSAGE_WITH_FILE_TRANSFER);
-
- // example URI: content://rcs/incoming_message
- URL_MATCHER.addURI(AUTHORITY, "incoming_message", INCOMING_MESSAGE);
-
- // example URI: content://rcs/incoming_message/45
- URL_MATCHER.addURI(AUTHORITY, "incoming_message/#", INCOMING_MESSAGE_WITH_ID);
-
- // example URI: content://rcs/outgoing_message
- URL_MATCHER.addURI(AUTHORITY, "outgoing_message", OUTGOING_MESSAGE);
-
- // example URI: content://rcs/outgoing_message/54
- URL_MATCHER.addURI(AUTHORITY, "outgoing_message/#", OUTGOING_MESSAGE_WITH_ID);
-
- // example URI: content://rcs/outgoing_message/54/delivery. Only supports queries
- URL_MATCHER.addURI(AUTHORITY, "outgoing_message/#/delivery", OUTGOING_MESSAGE_DELIVERY);
-
- // example URI: content://rcs/outgoing_message/9/delivery/4. Does not support queries
- URL_MATCHER.addURI(AUTHORITY, "outgoing_message/#/delivery/#",
- OUTGOING_MESSAGE_DELIVERY_WITH_ID);
-
- // example URI: content://rcs/thread/5/message, only supports querying.
- URL_MATCHER.addURI(AUTHORITY, "thread/#/message", UNIFIED_MESSAGE_ON_THREAD);
-
- // example URI: content://rcs/thread/5/message/40, only supports querying.
- URL_MATCHER.addURI(AUTHORITY, "thread/#/message/#", UNIFIED_MESSAGE_ON_THREAD_WITH_ID);
-
- // example URI: content://rcs/p2p_thread/3/incoming_message. Only available for inserting
- // incoming messages onto a 1 to 1 thread.
- URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/incoming_message",
- INCOMING_MESSAGE_ON_P2P_THREAD);
-
- // example URI: content://rcs/p2p_thread/11/incoming_message/45. Only supports querying
- URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/incoming_message/#",
- INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID);
-
- // example URI: content://rcs/p2p_thread/3/outgoing_message. Only available for inserting
- // outgoing messages onto a 1 to 1 thread.
- URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/outgoing_message",
- OUTGOING_MESSAGE_ON_P2P_THREAD);
-
- // example URI: content://rcs/p2p_thread/11/outgoing_message/46. Only supports querying
- URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/outgoing_message/#",
- OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID);
-
- // example URI: content://rcs/group_thread/3/incoming_message. Only available for inserting
- // incoming messages onto a group thread.
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/incoming_message",
- INCOMING_MESSAGE_ON_GROUP_THREAD);
-
- // example URI: content://rcs/group_thread/3/incoming_message/71. Only supports querying
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/incoming_message/#",
- INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID);
-
- // example URI: content://rcs/group_thread/3/outgoing_message. Only available for inserting
- // outgoing messages onto a group thread.
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/outgoing_message",
- OUTGOING_MESSAGE_ON_GROUP_THREAD);
-
- // example URI: content://rcs/group_thread/13/outgoing_message/72. Only supports querying
- URL_MATCHER.addURI(AUTHORITY, "group_thread/#/outgoing_message/#",
- OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID);
-
- // example URI: content://rcs/file_transfer/1. Does not support insertion
- URL_MATCHER.addURI(AUTHORITY, "file_transfer/#", FILE_TRANSFER_WITH_ID);
-
- // example URI: content://rcs/event
- URL_MATCHER.addURI(AUTHORITY, "event", EVENT);
-
- URL_MATCHER.addURI(AUTHORITY, "canonical-address", CANONICAL_ADDRESS);
- }
-
- @Override
- public boolean onCreate() {
- // Use the credential encrypted mmssms.db for RCS messages.
- mDbOpenHelper = MmsSmsDatabaseHelper.getInstanceForCe(getContext());
- mParticipantHelper = new RcsProviderParticipantHelper(mDbOpenHelper);
- mThreadHelper = new RcsProviderThreadHelper(mDbOpenHelper);
- mMessageHelper = new RcsProviderMessageHelper(mDbOpenHelper);
- mEventHelper = new RcsProviderEventHelper(mDbOpenHelper);
- mCanonicalAddressHelper = new RcsProviderCanonicalAddressHelper(mDbOpenHelper);
- return true;
- }
-
- /**
- * ContentResolver has a weird bug that if both query methods are overridden, it will always
- * pick the bundle one to call, but will still require us to override this one as it is
- * abstract. Work around by putting parameters in a bundle.
- */
- @Override
- public synchronized Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- Bundle bundle = new Bundle();
- bundle.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, selection);
- bundle.putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs);
- bundle.putString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER, sortOrder);
- return query(uri, projection, bundle, null);
- }
-
- @Override
- public synchronized Cursor query(Uri uri, String[] projection, Bundle queryArgs,
- CancellationSignal unused) {
- int match = URL_MATCHER.match(uri);
-
- String selection = null;
- String[] selectionArgs = null;
- String sortOrder = null;
-
- if (queryArgs != null) {
- selection = queryArgs.getString(ContentResolver.QUERY_ARG_SQL_SELECTION);
- selectionArgs = queryArgs.getStringArray(
- ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS);
- sortOrder = queryArgs.getString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER);
- }
-
- switch (match) {
- case UNIFIED_RCS_THREAD:
- return mThreadHelper.queryUnifiedThread(queryArgs);
- case UNIFIED_RCS_THREAD_WITH_ID:
- return mThreadHelper.queryUnifiedThreadUsingId(uri, projection);
- case PARTICIPANT:
- return mParticipantHelper.queryParticipant(queryArgs);
- case PARTICIPANT_WITH_ID:
- return mParticipantHelper.queryParticipantWithId(uri, projection);
- case PARTICIPANT_ALIAS_CHANGE_EVENT:
- Log.e(TAG, "Querying individual event types is not supported, uri: " + uri);
- break;
- case PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID:
- Log.e(TAG, "Querying participant events with id's is not supported, uri: " + uri);
- break;
- case P2P_THREAD:
- return mThreadHelper.query1to1Thread(projection, selection,
- selectionArgs, sortOrder);
- case P2P_THREAD_WITH_ID:
- return mThreadHelper.query1To1ThreadUsingId(uri, projection);
- case P2P_THREAD_PARTICIPANT:
- return mParticipantHelper.queryParticipantIn1To1Thread(uri);
- case P2P_THREAD_PARTICIPANT_WITH_ID:
- Log.e(TAG,
- "Querying participants in 1 to 1 threads via id's is not supported, uri: "
- + uri);
- break;
- case GROUP_THREAD:
- return mThreadHelper.queryGroupThread(projection, selection,
- selectionArgs, sortOrder);
- case GROUP_THREAD_WITH_ID:
- return mThreadHelper.queryGroupThreadUsingId(uri, projection);
- case GROUP_THREAD_PARTICIPANT:
- return mParticipantHelper.queryParticipantsInGroupThread(uri);
- case GROUP_THREAD_PARTICIPANT_WITH_ID:
- return mParticipantHelper.queryParticipantInGroupThreadWithId(uri);
- case GROUP_THREAD_PARTICIPANT_JOINED_EVENT:
- case GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID:
- case GROUP_THREAD_PARTICIPANT_LEFT_EVENT:
- case GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID:
- case GROUP_THREAD_NAME_CHANGE_EVENT:
- case GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID:
- case GROUP_THREAD_ICON_CHANGE_EVENT:
- case GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID:
- Log.e(TAG, "Querying individual event types is not supported, uri: " + uri);
- break;
- case UNIFIED_MESSAGE:
- return mMessageHelper.queryMessages(queryArgs);
- case UNIFIED_MESSAGE_WITH_ID:
- return mMessageHelper.queryUnifiedMessageWithId(uri);
- case UNIFIED_MESSAGE_WITH_FILE_TRANSFER:
- Log.e(TAG,
- "Querying file transfers through messages is not supported, uri: " + uri);
- case INCOMING_MESSAGE:
- return mMessageHelper.queryIncomingMessageWithSelection(selection, selectionArgs);
- case INCOMING_MESSAGE_WITH_ID:
- return mMessageHelper.queryIncomingMessageWithId(uri);
- case OUTGOING_MESSAGE:
- return mMessageHelper.queryOutgoingMessageWithSelection(selection, selectionArgs);
- case OUTGOING_MESSAGE_WITH_ID:
- return mMessageHelper.queryOutgoingMessageWithId(uri);
- case OUTGOING_MESSAGE_DELIVERY:
- return mMessageHelper.queryOutgoingMessageDeliveries(uri);
- case OUTGOING_MESSAGE_DELIVERY_WITH_ID:
- Log.e(TAG,
- "Querying deliveries with message and participant ids is not supported, "
- + "uri: "
- + uri);
- case UNIFIED_MESSAGE_ON_THREAD:
- return mMessageHelper.queryAllMessagesOnThread(uri, selection, selectionArgs);
- case UNIFIED_MESSAGE_ON_THREAD_WITH_ID:
- return mMessageHelper.queryUnifiedMessageWithIdInThread(uri);
- case INCOMING_MESSAGE_ON_P2P_THREAD:
- Log.e(TAG,
- "Querying incoming messages on P2P thread with selection is not "
- + "supported, uri: "
- + uri);
- break;
- case INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID:
- return mMessageHelper.queryUnifiedMessageWithIdInThread(uri);
- case OUTGOING_MESSAGE_ON_P2P_THREAD:
- Log.e(TAG,
- "Querying outgoing messages on P2P thread with selection is not "
- + "supported, uri: "
- + uri);
- break;
- case OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID:
- return mMessageHelper.queryUnifiedMessageWithIdInThread(uri);
- case INCOMING_MESSAGE_ON_GROUP_THREAD:
- Log.e(TAG,
- "Querying incoming messages on group thread with selection is not "
- + "supported, uri: "
- + uri);
- break;
- case INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
- return mMessageHelper.queryUnifiedMessageWithIdInThread(uri);
- case OUTGOING_MESSAGE_ON_GROUP_THREAD:
- Log.e(TAG,
- "Querying outgoing messages on group thread with selection is not "
- + "supported, uri: "
- + uri);
- break;
- case OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
- return mMessageHelper.queryUnifiedMessageWithIdInThread(uri);
- case FILE_TRANSFER_WITH_ID:
- return mMessageHelper.queryFileTransfer(uri);
- case EVENT:
- return mEventHelper.queryEvents(queryArgs);
- case CANONICAL_ADDRESS:
- String canonicalAddress = uri.getQueryParameter("address");
- return mCanonicalAddressHelper.getOrCreateCanonicalAddress(canonicalAddress);
- default:
- Log.e(TAG, "Invalid query: " + uri);
- }
-
- return null;
- }
-
- @Override
- public String getType(Uri uri) {
- return null;
- }
-
- @Override
- public synchronized Uri insert(Uri uri, ContentValues values) {
- int match = URL_MATCHER.match(uri);
- long rowId;
-
- switch (match) {
- case UNIFIED_RCS_THREAD:
- case UNIFIED_RCS_THREAD_WITH_ID:
- Log.e(TAG, "Inserting into unified thread view is not supported, uri: " + uri);
- break;
- case PARTICIPANT:
- return buildUriWithRowIdAppended(PARTICIPANT_URI_PREFIX,
- mParticipantHelper.insertParticipant(values));
- case PARTICIPANT_WITH_ID:
- Log.e(TAG, "Inserting participant with a specified ID is not supported, uri: "
- + uri);
- break;
- case PARTICIPANT_ALIAS_CHANGE_EVENT:
- return buildUriWithRowIdAppended(uri,
- mEventHelper.insertParticipantEvent(uri, values));
- case PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID:
- Log.e(TAG, "Inserting participant events with id's is not supported, uri: " + uri);
- break;
- case P2P_THREAD:
- return buildUriWithRowIdAppended(P2P_THREAD_URI_PREFIX,
- mThreadHelper.insert1To1Thread(values));
- case P2P_THREAD_WITH_ID:
- Log.e(TAG, "Inserting a thread with a specified ID is not supported, uri: " + uri);
- break;
- case P2P_THREAD_PARTICIPANT:
- Log.e(TAG,
- "Inserting a participant into a thread via content values is not "
- + "supported, uri: "
- + uri);
- break;
- case P2P_THREAD_PARTICIPANT_WITH_ID:
- Log.e(TAG,
- "Inserting participant into a thread via URI is not supported, uri: "
- + uri);
- break;
- case GROUP_THREAD:
- return buildUriWithRowIdAppended(GROUP_THREAD_URI_PREFIX,
- mThreadHelper.insertGroupThread(values));
- case GROUP_THREAD_WITH_ID:
- Log.e(TAG, "Inserting a thread with a specified ID is not supported, uri: " + uri);
- break;
- case GROUP_THREAD_PARTICIPANT_JOINED_EVENT:
- return buildUriWithRowIdAppended(uri,
- mEventHelper.insertParticipantJoinedEvent(uri, values));
- case GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID:
- Log.e(TAG, "Inserting thread events with id's is not supported, uri: " + uri);
- break;
- case GROUP_THREAD_PARTICIPANT_LEFT_EVENT:
- return buildUriWithRowIdAppended(uri,
- mEventHelper.insertParticipantLeftEvent(uri, values));
- case GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID:
- Log.e(TAG, "Inserting thread events with id's is not supported, uri: " + uri);
- break;
- case GROUP_THREAD_NAME_CHANGE_EVENT:
- return buildUriWithRowIdAppended(uri,
- mEventHelper.insertThreadNameChangeEvent(uri, values));
- case GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID:
- Log.e(TAG, "Inserting thread events with id's is not supported, uri: " + uri);
- break;
- case GROUP_THREAD_ICON_CHANGE_EVENT:
- return buildUriWithRowIdAppended(uri,
- mEventHelper.insertThreadIconChangeEvent(uri, values));
- case GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID:
- Log.e(TAG, "Inserting thread events with id's is not supported, uri: " + uri);
- break;
- case GROUP_THREAD_PARTICIPANT:
- rowId = mParticipantHelper.insertParticipantIntoGroupThread(values);
- if (rowId == TRANSACTION_FAILED) {
- return null;
- }
- return mParticipantHelper.getParticipantInThreadUri(values, rowId);
- case GROUP_THREAD_PARTICIPANT_WITH_ID:
- return returnUriAsIsIfSuccessful(uri,
- mParticipantHelper.insertParticipantIntoGroupThreadWithId(uri));
- case UNIFIED_MESSAGE:
- case UNIFIED_MESSAGE_WITH_ID:
- Log.e(TAG, "Inserting into unified message view is not supported, uri: " + uri);
- break;
- case UNIFIED_MESSAGE_WITH_FILE_TRANSFER:
- return buildUriWithRowIdAppended(FILE_TRANSFER_PREFIX,
- mMessageHelper.insertFileTransferToMessage(uri, values));
- case INCOMING_MESSAGE:
- case INCOMING_MESSAGE_WITH_ID:
- case OUTGOING_MESSAGE:
- case OUTGOING_MESSAGE_WITH_ID:
- Log.e(TAG, "Inserting a message without a thread is not supported, uri: "
- + uri);
- break;
- case OUTGOING_MESSAGE_DELIVERY:
- Log.e(TAG,
- "Inserting an outgoing message delivery without a participant is not "
- + "supported, uri: "
- + uri);
- break;
- case OUTGOING_MESSAGE_DELIVERY_WITH_ID:
- return returnUriAsIsIfSuccessful(uri,
- mMessageHelper.insertMessageDelivery(uri, values));
- case UNIFIED_MESSAGE_ON_THREAD:
- case UNIFIED_MESSAGE_ON_THREAD_WITH_ID:
- Log.e(TAG,
- "Inserting a message on unified thread view is not supported, uri: " + uri);
- break;
- case INCOMING_MESSAGE_ON_P2P_THREAD:
- return mMessageHelper.insertMessageOnThread(uri, values, /* isIncoming= */
- true, /* is1To1 */ true);
- case OUTGOING_MESSAGE_ON_P2P_THREAD:
- return mMessageHelper.insertMessageOnThread(uri, values, /* isIncoming= */
- false, /* is1To1 */ true);
- case INCOMING_MESSAGE_ON_GROUP_THREAD:
- return mMessageHelper.insertMessageOnThread(uri, values, /* isIncoming= */
- true, /* is1To1 */ false);
- case OUTGOING_MESSAGE_ON_GROUP_THREAD:
- return mMessageHelper.insertMessageOnThread(uri, values, /* isIncoming= */
- false, /* is1To1 */ false);
- case INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID:
- case OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID:
- case INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
- case OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
- Log.e(TAG, "Inserting a message with a specific id is not supported, uri: " + uri);
- break;
- case FILE_TRANSFER_WITH_ID:
- Log.e(TAG, "Inserting a file transfer without a message is not supported, uri: "
- + uri);
- break;
- case EVENT:
- Log.e(TAG,
- "Inserting event using unified event query is not supported, uri: " + uri);
- break;
- default:
- Log.e(TAG, "Invalid insert: " + uri);
- }
-
- return null;
- }
-
- @Override
- public synchronized int delete(Uri uri, String selection, String[] selectionArgs) {
- int match = URL_MATCHER.match(uri);
- int deletedCount = 0;
-
- switch (match) {
- case UNIFIED_RCS_THREAD:
- case UNIFIED_RCS_THREAD_WITH_ID:
- Log.e(TAG, "Deleting entries from unified view is not allowed: " + uri);
- break;
- case PARTICIPANT:
- Log.e(TAG, "Deleting participant with selection is not allowed: " + uri);
- break;
- case PARTICIPANT_WITH_ID:
- return mParticipantHelper.deleteParticipantWithId(uri);
- case PARTICIPANT_ALIAS_CHANGE_EVENT:
- Log.e(TAG, "Deleting participant events without id is not allowed: " + uri);
- break;
- case PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID:
- return mEventHelper.deleteParticipantEvent(uri);
- case P2P_THREAD:
- return mThreadHelper.delete1To1Thread(selection, selectionArgs);
- case P2P_THREAD_WITH_ID:
- return mThreadHelper.delete1To1ThreadWithId(uri);
- case P2P_THREAD_PARTICIPANT:
- Log.e(TAG, "Removing participant from 1 to 1 thread is not allowed, uri: " + uri);
- break;
- case GROUP_THREAD:
- return mThreadHelper.deleteGroupThread(selection, selectionArgs);
- case GROUP_THREAD_WITH_ID:
- return mThreadHelper.deleteGroupThreadWithId(uri);
- case GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID:
- return mEventHelper.deleteGroupThreadEvent(uri);
- case GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID:
- return mEventHelper.deleteGroupThreadEvent(uri);
- case GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID:
- return mEventHelper.deleteGroupThreadEvent(uri);
- case GROUP_THREAD_PARTICIPANT_JOINED_EVENT:
- case GROUP_THREAD_PARTICIPANT_LEFT_EVENT:
- case GROUP_THREAD_NAME_CHANGE_EVENT:
- case GROUP_THREAD_ICON_CHANGE_EVENT:
- Log.e(TAG, "Deleting thread events via selection is not allowed, uri: " + uri);
- break;
- case GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID:
- return mEventHelper.deleteGroupThreadEvent(uri);
- case GROUP_THREAD_PARTICIPANT:
- Log.e(TAG,
- "Deleting a participant from group thread via selection is not allowed, "
- + "uri: "
- + uri);
- break;
- case GROUP_THREAD_PARTICIPANT_WITH_ID:
- return mParticipantHelper.deleteParticipantFromGroupThread(uri);
- case UNIFIED_MESSAGE:
- Log.e(TAG,
- "Deleting message from unified view with selection is not allowed: " + uri);
- break;
- case UNIFIED_MESSAGE_WITH_ID:
- Log.e(TAG, "Deleting message from unified view with id is not allowed: " + uri);
- break;
- case UNIFIED_MESSAGE_WITH_FILE_TRANSFER:
- Log.e(TAG, "Deleting file transfer using message uri is not allowed, uri: " + uri);
- break;
- case INCOMING_MESSAGE:
- return mMessageHelper.deleteIncomingMessageWithSelection(selection, selectionArgs);
- case INCOMING_MESSAGE_WITH_ID:
- return mMessageHelper.deleteIncomingMessageWithId(uri);
- case OUTGOING_MESSAGE:
- return mMessageHelper.deleteOutgoingMessageWithSelection(selection, selectionArgs);
- case OUTGOING_MESSAGE_WITH_ID:
- return mMessageHelper.deleteOutgoingMessageWithId(uri);
- case OUTGOING_MESSAGE_DELIVERY:
- case OUTGOING_MESSAGE_DELIVERY_WITH_ID:
- Log.e(TAG, "Deleting message deliveries is not supported, uri: " + uri);
- break;
- case UNIFIED_MESSAGE_ON_THREAD:
- case UNIFIED_MESSAGE_ON_THREAD_WITH_ID:
- case INCOMING_MESSAGE_ON_P2P_THREAD:
- case INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID:
- case OUTGOING_MESSAGE_ON_P2P_THREAD:
- case OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID:
- case INCOMING_MESSAGE_ON_GROUP_THREAD:
- case INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
- case OUTGOING_MESSAGE_ON_GROUP_THREAD:
- case OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
- Log.e(TAG, "Deleting messages using thread uris is not supported, uri: " + uri);
- break;
- case FILE_TRANSFER_WITH_ID:
- return mMessageHelper.deleteFileTransfer(uri);
- case EVENT:
- Log.e(TAG, "Deleting events using unified event uri is not supported, uri: " + uri);
- break;
- default:
- Log.e(TAG, "Invalid delete: " + uri);
- }
-
- return deletedCount;
- }
-
- @Override
- public synchronized int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
- int match = URL_MATCHER.match(uri);
- int updatedCount = 0;
-
- switch (match) {
- case UNIFIED_RCS_THREAD:
- case UNIFIED_RCS_THREAD_WITH_ID:
- Log.e(TAG, "Updating unified thread view is not supported, uri: " + uri);
- break;
- case PARTICIPANT:
- Log.e(TAG, "Updating participants with selection is not supported, uri: " + uri);
- break;
- case PARTICIPANT_WITH_ID:
- return mParticipantHelper.updateParticipantWithId(values, uri);
- case PARTICIPANT_ALIAS_CHANGE_EVENT:
- case PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID:
- Log.e(TAG, "Updating events is not supported, uri: " + uri);
- break;
- case P2P_THREAD:
- return mThreadHelper.update1To1Thread(values, selection, selectionArgs);
- case P2P_THREAD_WITH_ID:
- return mThreadHelper.update1To1ThreadWithId(values, uri);
- case P2P_THREAD_PARTICIPANT:
- Log.e(TAG, "Updating junction table entries is not supported, uri: " + uri);
- break;
- case GROUP_THREAD:
- return mThreadHelper.updateGroupThread(values, selection, selectionArgs);
- case GROUP_THREAD_WITH_ID:
- return mThreadHelper.updateGroupThreadWithId(values, uri);
- case GROUP_THREAD_PARTICIPANT_JOINED_EVENT:
- case GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID:
- case GROUP_THREAD_PARTICIPANT_LEFT_EVENT:
- case GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID:
- case GROUP_THREAD_NAME_CHANGE_EVENT:
- case GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID:
- case GROUP_THREAD_ICON_CHANGE_EVENT:
- case GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID:
- Log.e(TAG, "Updating thread events is not supported, uri: " + uri);
- break;
- case GROUP_THREAD_PARTICIPANT:
- case GROUP_THREAD_PARTICIPANT_WITH_ID:
- Log.e(TAG, "Updating junction table entries is not supported, uri: " + uri);
- break;
- case UNIFIED_MESSAGE:
- case UNIFIED_MESSAGE_WITH_ID:
- Log.e(TAG, "Updating unified message view is not supported, uri: " + uri);
- break;
- case UNIFIED_MESSAGE_WITH_FILE_TRANSFER:
- Log.e(TAG,
- "Updating file transfer using unified message uri is not supported, uri: "
- + uri);
- case INCOMING_MESSAGE:
- Log.e(TAG,
- "Updating an incoming message via selection is not supported, uri: " + uri);
- break;
- case INCOMING_MESSAGE_WITH_ID:
- return mMessageHelper.updateIncomingMessage(uri, values);
- case OUTGOING_MESSAGE:
- Log.e(TAG,
- "Updating an outgoing message via selection is not supported, uri: " + uri);
- break;
- case OUTGOING_MESSAGE_WITH_ID:
- return mMessageHelper.updateOutgoingMessage(uri, values);
- case OUTGOING_MESSAGE_DELIVERY:
- Log.e(TAG, "Updating message deliveries using message uris is not supported, uri: "
- + uri);
- break;
- case OUTGOING_MESSAGE_DELIVERY_WITH_ID:
- return mMessageHelper.updateDelivery(uri, values);
- case UNIFIED_MESSAGE_ON_THREAD:
- case UNIFIED_MESSAGE_ON_THREAD_WITH_ID:
- case INCOMING_MESSAGE_ON_P2P_THREAD:
- case INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID:
- case OUTGOING_MESSAGE_ON_P2P_THREAD:
- case OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID:
- case INCOMING_MESSAGE_ON_GROUP_THREAD:
- case INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
- case OUTGOING_MESSAGE_ON_GROUP_THREAD:
- case OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
- Log.e(TAG, "Updating messages using threads uris is not supported, uri: " + uri);
- break;
- case FILE_TRANSFER_WITH_ID:
- return mMessageHelper.updateFileTransfer(uri, values);
- case EVENT:
- Log.e(TAG, "Updating events is not supported, uri: " + uri);
- break;
- default:
- Log.e(TAG, "Invalid update: " + uri);
- }
-
- return updatedCount;
- }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderCanonicalAddressHelper.java b/src/com/android/providers/telephony/RcsProviderCanonicalAddressHelper.java
deleted file mode 100644
index 496b512..0000000
--- a/src/com/android/providers/telephony/RcsProviderCanonicalAddressHelper.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.android.providers.telephony;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.provider.BaseColumns;
-import android.provider.Telephony;
-
-public class RcsProviderCanonicalAddressHelper {
- SQLiteOpenHelper mSQLiteOpenHelper;
-
- RcsProviderCanonicalAddressHelper(SQLiteOpenHelper sqLiteOpenHelper) {
- mSQLiteOpenHelper = sqLiteOpenHelper;
- }
-
- Cursor getOrCreateCanonicalAddress(String canonicalAddress) {
- SQLiteDatabase db = mSQLiteOpenHelper.getReadableDatabase();
-
- Cursor cursor = db.query(
- MmsSmsProvider.TABLE_CANONICAL_ADDRESSES,
- new String[]{BaseColumns._ID}, Telephony.CanonicalAddressesColumns.ADDRESS + "=?",
- new String[]{canonicalAddress}, null, null, null);
-
- if (cursor != null && cursor.getCount() > 0) {
- return cursor;
- }
-
- if (cursor != null) {
- cursor.close();
- }
-
- return insertCanonicalAddress(canonicalAddress);
- }
-
- private Cursor insertCanonicalAddress(String canonicalAddress) {
- ContentValues contentValues = new ContentValues();
- contentValues.put(Telephony.CanonicalAddressesColumns.ADDRESS, canonicalAddress);
-
- SQLiteDatabase db = mSQLiteOpenHelper.getWritableDatabase();
-
- long id = db.insert(MmsSmsProvider.TABLE_CANONICAL_ADDRESSES, null, contentValues);
-
- if (id == -1) {
- return null;
- }
-
- MatrixCursor matrixCursor = new MatrixCursor(new String[]{BaseColumns._ID}, 1);
- matrixCursor.addRow(new Object[]{id});
-
- return matrixCursor;
- }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderEventHelper.java b/src/com/android/providers/telephony/RcsProviderEventHelper.java
deleted file mode 100644
index c6a6fc6..0000000
--- a/src/com/android/providers/telephony/RcsProviderEventHelper.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantEventColumns.NEW_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.ICON_CHANGED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.NAME_CHANGED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_JOINED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_LEFT_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.DESTINATION_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.EVENT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.EVENT_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_ICON_URI_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.SOURCE_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-import static android.telephony.ims.RcsEventQueryParams.ALL_EVENTS;
-import static android.telephony.ims.RcsEventQueryParams.ALL_GROUP_THREAD_EVENTS;
-import static android.telephony.ims.RcsEventQueryParams.EVENT_QUERY_PARAMETERS_KEY;
-
-import static android.telephony.ims.RcsQueryContinuationToken.EVENT_QUERY_CONTINUATION_TOKEN_TYPE;
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_EVENT_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_THREAD_EVENT_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_UNIFIED_EVENT_VIEW;
-import static com.android.providers.telephony.RcsProvider.TAG;
-import static com.android.providers.telephony.RcsProviderThreadHelper.getThreadIdFromUri;
-import static com.android.providers.telephony.RcsProviderUtil.INSERTION_FAILED;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.telephony.ims.RcsEventQueryParams;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Constants and helpers related to events for {@link RcsProvider} to keep the code clean.
- *
- * @hide
- */
-class RcsProviderEventHelper {
- private static final int PARTICIPANT_INDEX_IN_EVENT_URI = 1;
- private static final int EVENT_INDEX_IN_EVENT_URI = 3;
-
- @VisibleForTesting
- public static void createRcsEventTables(SQLiteDatabase db) {
- Log.d(TAG, "Creating event tables");
-
- // Add the event tables
- db.execSQL("CREATE TABLE " + RCS_THREAD_EVENT_TABLE + "(" + EVENT_ID_COLUMN
- + " INTEGER PRIMARY KEY AUTOINCREMENT, " + RCS_THREAD_ID_COLUMN + " INTEGER, "
- + SOURCE_PARTICIPANT_ID_COLUMN + " INTEGER, " + EVENT_TYPE_COLUMN + " INTEGER, "
- + TIMESTAMP_COLUMN + " INTEGER, " + DESTINATION_PARTICIPANT_ID_COLUMN + " INTEGER, "
- + NEW_ICON_URI_COLUMN + " TEXT, " + NEW_NAME_COLUMN + " TEXT, " + " FOREIGN KEY ("
- + RCS_THREAD_ID_COLUMN + ") REFERENCES " + RCS_THREAD_TABLE + " ("
- + RCS_THREAD_ID_COLUMN + "), FOREIGN KEY (" + SOURCE_PARTICIPANT_ID_COLUMN
- + ") REFERENCES " + RCS_PARTICIPANT_TABLE + " (" + RCS_PARTICIPANT_ID_COLUMN
- + "))");
-
- db.execSQL("CREATE TABLE " + RCS_PARTICIPANT_EVENT_TABLE + "(" + EVENT_ID_COLUMN
- + " INTEGER PRIMARY KEY AUTOINCREMENT, " + SOURCE_PARTICIPANT_ID_COLUMN +
- " INTEGER, " + TIMESTAMP_COLUMN + " INTEGER, "
- + NEW_ALIAS_COLUMN + " TEXT," + " FOREIGN KEY (" + SOURCE_PARTICIPANT_ID_COLUMN
- + ") REFERENCES " + RCS_PARTICIPANT_TABLE + " (" + RCS_PARTICIPANT_ID_COLUMN
- + "))");
-
- // Add the views
-
- // The following is a unified event view that puts every entry in both tables into one query
- db.execSQL("CREATE VIEW " + RCS_UNIFIED_EVENT_VIEW + " AS "
- + "SELECT " + PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE + " AS " + EVENT_TYPE_COLUMN
- + ", " + EVENT_ID_COLUMN + ", " + SOURCE_PARTICIPANT_ID_COLUMN + ", "
- + TIMESTAMP_COLUMN + ", " + NEW_ALIAS_COLUMN + ", NULL as " + RCS_THREAD_ID_COLUMN
- + ", NULL as " + DESTINATION_PARTICIPANT_ID_COLUMN + ", NULL as "
- + NEW_ICON_URI_COLUMN + ", NULL as " + NEW_NAME_COLUMN + " "
- + "FROM " + RCS_PARTICIPANT_EVENT_TABLE + " "
- + "UNION "
- + "SELECT " + EVENT_TYPE_COLUMN + ", " + EVENT_ID_COLUMN + ", "
- + SOURCE_PARTICIPANT_ID_COLUMN + ", " + TIMESTAMP_COLUMN + ", "
- + "NULL as " + NEW_ALIAS_COLUMN + ", " + RCS_THREAD_ID_COLUMN + ", "
- + DESTINATION_PARTICIPANT_ID_COLUMN + ", " + NEW_ICON_URI_COLUMN + ", "
- + NEW_NAME_COLUMN + " "
- + "FROM " + RCS_THREAD_EVENT_TABLE);
- }
-
- private final SQLiteOpenHelper mSqLiteOpenHelper;
-
- Cursor queryEvents(Bundle bundle) {
- RcsEventQueryParams queryParameters = null;
- RcsQueryContinuationToken continuationToken = null;
-
- if (bundle != null) {
- queryParameters = bundle.getParcelable(EVENT_QUERY_PARAMETERS_KEY);
- continuationToken = bundle.getParcelable(QUERY_CONTINUATION_TOKEN);
- }
-
- if (continuationToken != null) {
- return RcsProviderUtil.performContinuationQuery(mSqLiteOpenHelper.getReadableDatabase(),
- continuationToken);
- }
-
- // if no query parameters were entered, build an empty query parameters object
- if (queryParameters == null) {
- queryParameters = new RcsEventQueryParams.Builder().build();
- }
-
- return performInitialQuery(queryParameters);
- }
-
- private Cursor performInitialQuery(RcsEventQueryParams queryParameters) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- StringBuilder rawQuery = new StringBuilder("SELECT * FROM ").append(RCS_UNIFIED_EVENT_VIEW);
-
- int eventType = queryParameters.getEventType();
- if (eventType != ALL_EVENTS) {
- rawQuery.append(" WHERE ").append(EVENT_TYPE_COLUMN);
- if (eventType == ALL_GROUP_THREAD_EVENTS) {
- rawQuery.append(" IN (").append(
- PARTICIPANT_JOINED_EVENT_TYPE).append(", ").append(
- PARTICIPANT_LEFT_EVENT_TYPE).append(", ").append(
- ICON_CHANGED_EVENT_TYPE).append(", ").append(
- NAME_CHANGED_EVENT_TYPE).append(
- ")");
- } else {
- rawQuery.append("=").append(eventType);
- }
- }
-
- rawQuery.append(" ORDER BY ");
-
- int sortingProperty = queryParameters.getSortingProperty();
- if (sortingProperty == RcsEventQueryParams.SORT_BY_TIMESTAMP) {
- rawQuery.append(TIMESTAMP_COLUMN);
- } else {
- rawQuery.append(EVENT_ID_COLUMN);
- }
-
- rawQuery.append(queryParameters.getSortDirection() ? " ASC " : " DESC ");
-
- RcsProviderUtil.appendLimit(rawQuery, queryParameters.getLimit());
- String rawQueryAsString = rawQuery.toString();
- Cursor cursor = db.rawQuery(rawQueryAsString, null);
-
- // if the query was paginated, build the next query
- int limit = queryParameters.getLimit();
- if (limit > 0) {
- RcsProviderUtil.createContinuationTokenBundle(cursor,
- new RcsQueryContinuationToken(EVENT_QUERY_CONTINUATION_TOKEN_TYPE,
- rawQueryAsString, limit, limit), QUERY_CONTINUATION_TOKEN);
- }
-
- return cursor;
- }
-
- RcsProviderEventHelper(SQLiteOpenHelper sqLiteOpenHelper) {
- mSqLiteOpenHelper = sqLiteOpenHelper;
- }
-
- long insertParticipantEvent(Uri uri, ContentValues values) {
- String participantId = getParticipantIdFromUri(uri);
-
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- values.put(SOURCE_PARTICIPANT_ID_COLUMN, participantId);
- long rowId = db.insert(RCS_PARTICIPANT_EVENT_TABLE, SOURCE_PARTICIPANT_ID_COLUMN, values);
- values.remove(SOURCE_PARTICIPANT_ID_COLUMN);
-
- if (rowId == INSERTION_FAILED) {
- return TRANSACTION_FAILED;
- }
-
- return rowId;
- }
-
- long insertParticipantJoinedEvent(Uri uri, ContentValues values) {
- return insertGroupThreadEvent(uri, values, PARTICIPANT_JOINED_EVENT_TYPE);
- }
-
- long insertParticipantLeftEvent(Uri uri, ContentValues values) {
- return insertGroupThreadEvent(uri, values, PARTICIPANT_LEFT_EVENT_TYPE);
- }
-
- long insertThreadNameChangeEvent(Uri uri, ContentValues values) {
- return insertGroupThreadEvent(uri, values, NAME_CHANGED_EVENT_TYPE);
- }
-
- long insertThreadIconChangeEvent(Uri uri, ContentValues values) {
- return insertGroupThreadEvent(uri, values, ICON_CHANGED_EVENT_TYPE);
- }
-
- private long insertGroupThreadEvent(Uri uri, ContentValues valuesParameter,
- int eventType) {
- String threadId = getThreadIdFromUri(uri);
-
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- ContentValues values = new ContentValues(valuesParameter);
- values.put(EVENT_TYPE_COLUMN, eventType);
- values.put(RCS_THREAD_ID_COLUMN, threadId);
- long rowId = db.insert(RCS_THREAD_EVENT_TABLE, EVENT_ID_COLUMN, values);
-
- if (rowId == INSERTION_FAILED) {
- return TRANSACTION_FAILED;
- }
-
- return rowId;
- }
-
- int deleteParticipantEvent(Uri uri) {
- String eventId = getEventIdFromEventUri(uri);
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
- return db.delete(RCS_PARTICIPANT_EVENT_TABLE, EVENT_ID_COLUMN + "=?",
- new String[]{eventId});
- }
-
- int deleteGroupThreadEvent(Uri uri) {
- String eventId = getEventIdFromEventUri(uri);
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
- return db.delete(RCS_THREAD_EVENT_TABLE, EVENT_ID_COLUMN + "=?", new String[]{eventId});
- }
-
- private String getEventIdFromEventUri(Uri uri) {
- return uri.getPathSegments().get(EVENT_INDEX_IN_EVENT_URI);
- }
-
- private String getParticipantIdFromUri(Uri uri) {
- return uri.getPathSegments().get(PARTICIPANT_INDEX_IN_EVENT_URI);
- }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderMessageHelper.java b/src/com/android/providers/telephony/RcsProviderMessageHelper.java
deleted file mode 100644
index 670c641..0000000
--- a/src/com/android/providers/telephony/RcsProviderMessageHelper.java
+++ /dev/null
@@ -1,707 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.RcsColumns.CONTENT_AND_AUTHORITY;
-import static android.provider.Telephony.RcsColumns.Rcs1To1ThreadColumns.RCS_1_TO_1_THREAD_URI_PART;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.CONTENT_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.CONTENT_URI_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.FILE_SIZE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.FILE_TRANSFER_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.HEIGHT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.DURATION_MILLIS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.PREVIEW_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.PREVIEW_URI_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.SESSION_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.SUCCESSFULLY_TRANSFERRED_BYTES;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.TRANSFER_STATUS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.WIDTH_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.RCS_GROUP_THREAD_URI_PART;
-import static android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns.ARRIVAL_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns.INCOMING_MESSAGE_URI_PART;
-import static android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns.SENDER_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.GLOBAL_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.LATITUDE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.LONGITUDE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_TEXT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.ORIGINATION_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.STATUS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.SUB_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageDeliveryColumns.DELIVERED_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsOutgoingMessageColumns.OUTGOING_MESSAGE_URI_PART;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MESSAGE_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MESSAGE_TYPE_INCOMING;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MESSAGE_TYPE_OUTGOING;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.UNIFIED_INCOMING_MESSAGE_VIEW;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.UNIFIED_OUTGOING_MESSAGE_VIEW;
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-import static android.telephony.ims.RcsMessageQueryParams.MESSAGE_QUERY_PARAMETERS_KEY;
-import static android.telephony.ims.RcsMessageQueryParams.THREAD_ID_NOT_SET;
-
-import static android.telephony.ims.RcsQueryContinuationToken.MESSAGE_QUERY_CONTINUATION_TOKEN_TYPE;
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static com.android.providers.telephony.RcsProvider.RCS_FILE_TRANSFER_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_INCOMING_MESSAGE_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_MESSAGE_DELIVERY_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_MESSAGE_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_OUTGOING_MESSAGE_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_THREAD_JUNCTION_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.TAG;
-import static com.android.providers.telephony.RcsProvider.UNIFIED_MESSAGE_VIEW;
-import static com.android.providers.telephony.RcsProviderThreadHelper.getThreadIdFromUri;
-import static com.android.providers.telephony.RcsProviderUtil.INSERTION_FAILED;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns;
-import android.provider.Telephony.RcsColumns.RcsMessageDeliveryColumns;
-import android.telephony.ims.RcsMessageQueryParams;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Constants and helpers related to messages for {@link RcsProvider} to keep the code clean.
- *
- * @hide
- */
-public class RcsProviderMessageHelper {
- private static final int MESSAGE_ID_INDEX_IN_URI = 1;
- private static final int MESSAGE_ID_INDEX_IN_THREAD_URI = 3;
-
- private final SQLiteOpenHelper mSqLiteOpenHelper;
-
- @VisibleForTesting
- public static void createRcsMessageTables(SQLiteDatabase db) {
- Log.d(TAG, "Creating message tables");
-
- // Add the message tables
- db.execSQL("CREATE TABLE " + RCS_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN
- + " INTEGER PRIMARY KEY AUTOINCREMENT, " + RCS_THREAD_ID_COLUMN + " INTEGER, "
- + GLOBAL_ID_COLUMN + " TEXT, " + SUB_ID_COLUMN + " INTEGER, " + MESSAGE_TEXT_COLUMN
- + " TEXT," + LATITUDE_COLUMN + " REAL, " + LONGITUDE_COLUMN + " REAL, "
- + STATUS_COLUMN + " INTEGER, " + ORIGINATION_TIMESTAMP_COLUMN
- + " INTEGER, FOREIGN KEY(" + RCS_THREAD_ID_COLUMN + ") REFERENCES "
- + RCS_THREAD_TABLE + "(" + RCS_THREAD_ID_COLUMN + "))");
-
- db.execSQL("CREATE TABLE " + RCS_INCOMING_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN
- + " INTEGER PRIMARY KEY, " + SENDER_PARTICIPANT_ID_COLUMN + " INTEGER, "
- + ARRIVAL_TIMESTAMP_COLUMN + " INTEGER, "
- + RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN + " INTEGER, FOREIGN KEY ("
- + MESSAGE_ID_COLUMN + ") REFERENCES " + RCS_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN
- + "))");
-
- db.execSQL("CREATE TABLE " + RCS_OUTGOING_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN
- + " INTEGER PRIMARY KEY, FOREIGN KEY (" + MESSAGE_ID_COLUMN + ") REFERENCES "
- + RCS_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN + "))");
-
- db.execSQL("CREATE TABLE " + RCS_MESSAGE_DELIVERY_TABLE + "(" + MESSAGE_ID_COLUMN
- + " INTEGER, " + RCS_PARTICIPANT_ID_COLUMN + " INTEGER, "
- + DELIVERED_TIMESTAMP_COLUMN + " INTEGER, "
- + RcsMessageDeliveryColumns.SEEN_TIMESTAMP_COLUMN + " INTEGER, "
- + "CONSTRAINT message_delivery PRIMARY KEY (" + MESSAGE_ID_COLUMN + ", "
- + RCS_PARTICIPANT_ID_COLUMN + "), FOREIGN KEY (" + MESSAGE_ID_COLUMN
- + ") REFERENCES " + RCS_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN + "), FOREIGN KEY ("
- + RCS_PARTICIPANT_ID_COLUMN + ") REFERENCES " + RCS_PARTICIPANT_TABLE + "("
- + RCS_PARTICIPANT_ID_COLUMN + "))");
-
- db.execSQL("CREATE TABLE " + RCS_FILE_TRANSFER_TABLE + " (" + FILE_TRANSFER_ID_COLUMN
- + " INTEGER PRIMARY KEY AUTOINCREMENT, " + MESSAGE_ID_COLUMN + " INTEGER, "
- + SESSION_ID_COLUMN + " TEXT, " + CONTENT_URI_COLUMN + " TEXT, "
- + CONTENT_TYPE_COLUMN + " TEXT, " + FILE_SIZE_COLUMN + " INTEGER, "
- + SUCCESSFULLY_TRANSFERRED_BYTES + " INTEGER, " + TRANSFER_STATUS_COLUMN +
- " INTEGER, " + WIDTH_COLUMN + " INTEGER, " + HEIGHT_COLUMN + " INTEGER, "
- + DURATION_MILLIS_COLUMN + " INTEGER, " + PREVIEW_URI_COLUMN + " TEXT, "
- + PREVIEW_TYPE_COLUMN + " TEXT, FOREIGN KEY (" + MESSAGE_ID_COLUMN + ") REFERENCES "
- + RCS_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN + "))");
-
- // Add the views
- //
- // The following view inner joins incoming messages with all messages, inner joins outgoing
- // messages with all messages, and unions them together, while also adding an is_incoming
- // column for easily telling where the record came from. This may have been achieved with
- // an outer join but SQLite doesn't support them.
- //
- // CREATE VIEW unified_message_view AS
- //
- // SELECT rcs_message.rcs_message_row_id,
- // rcs_message.rcs_thread_id,
- // rcs_message.rcs_message_global_id,
- // rcs_message.sub_id,
- // rcs_message.status,
- // rcs_message.origination_timestamp,
- // rcs_message.rcs_text,
- // rcs_message.latitude,
- // rcs_message.longitude,
- // 0 AS sender_participant,
- // 0 AS arrival_timestamp,
- // 0 AS seen_timestamp,
- // outgoing AS message_type
- //
- // FROM rcs_message INNER JOIN rcs_outgoing_message
- // ON rcs_message.rcs_message_row_id=rcs_outgoing_message.rcs_message_row_id
- //
- // UNION
- //
- // SELECT rcs_message.rcs_message_row_id,
- // rcs_message.rcs_thread_id,
- // rcs_message.rcs_message_global_id,
- // rcs_message.sub_id,
- // rcs_message.status,
- // rcs_message.origination_timestamp,
- // rcs_message.rcs_text,
- // rcs_message.latitude,
- // rcs_message.longitude,
- // rcs_incoming_message.sender_participant,
- // rcs_incoming_message.arrival_timestamp,
- // rcs_incoming_message.seen_timestamp,
- // incoming AS message_type
- //
- // FROM rcs_message INNER JOIN rcs_incoming_message
- // ON rcs_message.rcs_message_row_id=rcs_incoming_message.rcs_message_row_id
- //
- db.execSQL("CREATE VIEW " + UNIFIED_MESSAGE_VIEW + " AS SELECT "
- + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + GLOBAL_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + SUB_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + STATUS_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + ORIGINATION_TIMESTAMP_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + MESSAGE_TEXT_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + LATITUDE_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + LONGITUDE_COLUMN + ", "
- + "0 AS " + SENDER_PARTICIPANT_ID_COLUMN + ", "
- + "0 AS " + ARRIVAL_TIMESTAMP_COLUMN + ", "
- + "0 AS " + RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN + ", "
- + MESSAGE_TYPE_OUTGOING + " AS " + MESSAGE_TYPE_COLUMN
- + " FROM " + RCS_MESSAGE_TABLE + " INNER JOIN " + RCS_OUTGOING_MESSAGE_TABLE
- + " ON " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "="
- + RCS_OUTGOING_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN
- + " UNION SELECT "
- + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + GLOBAL_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + SUB_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + STATUS_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + ORIGINATION_TIMESTAMP_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + MESSAGE_TEXT_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + LATITUDE_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + LONGITUDE_COLUMN + ", "
- + RCS_INCOMING_MESSAGE_TABLE + "." + SENDER_PARTICIPANT_ID_COLUMN + ", "
- + RCS_INCOMING_MESSAGE_TABLE + "." + ARRIVAL_TIMESTAMP_COLUMN + ", "
- + RCS_INCOMING_MESSAGE_TABLE + "." + RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN
- + ", "
- + MESSAGE_TYPE_INCOMING + " AS " + MESSAGE_TYPE_COLUMN
- + " FROM " + RCS_MESSAGE_TABLE + " INNER JOIN " + RCS_INCOMING_MESSAGE_TABLE
- + " ON " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "="
- + RCS_INCOMING_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN);
-
- // The following view inner joins incoming messages with all messages
- //
- // CREATE VIEW unified_incoming_message_view AS
- //
- // SELECT rcs_message.rcs_message_row_id,
- // rcs_message.rcs_thread_id,
- // rcs_message.rcs_message_global_id,
- // rcs_message.sub_id,
- // rcs_message.status,
- // rcs_message.origination_timestamp,
- // rcs_message.rcs_text,
- // rcs_message.latitude,
- // rcs_message.longitude,
- // rcs_incoming_message.sender_participant,
- // rcs_incoming_message.arrival_timestamp,
- // rcs_incoming_message.seen_timestamp,
- //
- // FROM rcs_message INNER JOIN rcs_incoming_message
- // ON rcs_message.rcs_message_row_id=rcs_incoming_message.rcs_message_row_id
-
- db.execSQL("CREATE VIEW " + UNIFIED_INCOMING_MESSAGE_VIEW + " AS SELECT "
- + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + GLOBAL_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + SUB_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + STATUS_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + ORIGINATION_TIMESTAMP_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + MESSAGE_TEXT_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + LATITUDE_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + LONGITUDE_COLUMN + ", "
- + RCS_INCOMING_MESSAGE_TABLE + "." + SENDER_PARTICIPANT_ID_COLUMN + ", "
- + RCS_INCOMING_MESSAGE_TABLE + "." + ARRIVAL_TIMESTAMP_COLUMN + ", "
- + RCS_INCOMING_MESSAGE_TABLE + "." + RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN
- + " FROM " + RCS_MESSAGE_TABLE + " INNER JOIN " + RCS_INCOMING_MESSAGE_TABLE
- + " ON " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "="
- + RCS_INCOMING_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN);
-
- // The following view inner joins outgoing messages with all messages.
- //
- // CREATE VIEW unified_outgoing_message AS
- //
- // SELECT rcs_message.rcs_message_row_id,
- // rcs_message.rcs_thread_id,
- // rcs_message.rcs_message_global_id,
- // rcs_message.sub_id,
- // rcs_message.status,
- // rcs_message.origination_timestamp
- // rcs_message.rcs_text,
- // rcs_message.latitude,
- // rcs_message.longitude,
- //
- // FROM rcs_message INNER JOIN rcs_outgoing_message
- // ON rcs_message.rcs_message_row_id=rcs_outgoing_message.rcs_message_row_id
-
- db.execSQL("CREATE VIEW " + UNIFIED_OUTGOING_MESSAGE_VIEW + " AS SELECT "
- + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + GLOBAL_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + SUB_ID_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + STATUS_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + ORIGINATION_TIMESTAMP_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + MESSAGE_TEXT_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + LATITUDE_COLUMN + ", "
- + RCS_MESSAGE_TABLE + "." + LONGITUDE_COLUMN
- + " FROM " + RCS_MESSAGE_TABLE + " INNER JOIN " + RCS_OUTGOING_MESSAGE_TABLE
- + " ON " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "="
- + RCS_OUTGOING_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN);
-
- // Add triggers
-
- // Delete the corresponding rcs_message row upon deleting a row in rcs_incoming_message
- //
- // CREATE TRIGGER delete_common_message_after_incoming
- // AFTER DELETE ON rcs_incoming_message
- // BEGIN
- // DELETE FROM rcs_message WHERE rcs_message.rcs_message_row_id=OLD.rcs_message_row_id;
- // END
- db.execSQL("CREATE TRIGGER deleteCommonMessageAfterIncoming AFTER DELETE ON "
- + RCS_INCOMING_MESSAGE_TABLE + " BEGIN DELETE FROM " + RCS_MESSAGE_TABLE
- + " WHERE " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "=OLD."
- + MESSAGE_ID_COLUMN + "; END");
-
- // Delete the corresponding rcs_message row upon deleting a row in rcs_outgoing_message
- //
- // CREATE TRIGGER delete_common_message_after_outgoing
- // AFTER DELETE ON rcs_outgoing_message
- // BEGIN
- // DELETE FROM rcs_message WHERE rcs_message.rcs_message_row_id=OLD.rcs_message_row_id;
- // END
- db.execSQL("CREATE TRIGGER deleteCommonMessageAfterOutgoing AFTER DELETE ON "
- + RCS_OUTGOING_MESSAGE_TABLE + " BEGIN DELETE FROM " + RCS_MESSAGE_TABLE
- + " WHERE " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "=OLD."
- + MESSAGE_ID_COLUMN + "; END");
- }
-
- RcsProviderMessageHelper(SQLiteOpenHelper sqLiteOpenHelper) {
- mSqLiteOpenHelper = sqLiteOpenHelper;
- }
-
- Cursor queryMessages(Bundle bundle) {
- RcsMessageQueryParams queryParameters = null;
- RcsQueryContinuationToken continuationToken = null;
-
- if (bundle != null) {
- queryParameters = bundle.getParcelable(MESSAGE_QUERY_PARAMETERS_KEY);
- continuationToken = bundle.getParcelable(QUERY_CONTINUATION_TOKEN);
- }
-
- if (continuationToken != null) {
- return RcsProviderUtil.performContinuationQuery(mSqLiteOpenHelper.getReadableDatabase(),
- continuationToken);
- }
-
- // if no parameters were entered, build an empty query parameters object
- if (queryParameters == null) {
- queryParameters = new RcsMessageQueryParams.Builder().build();
- }
-
- return performInitialQuery(queryParameters);
- }
-
- private Cursor performInitialQuery(RcsMessageQueryParams queryParameters) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-
- StringBuilder rawQuery = new StringBuilder("SELECT * FROM ").append(UNIFIED_MESSAGE_VIEW);
-
- int messageType = queryParameters.getMessageType();
- String messageLike = queryParameters.getMessageLike();
- int threadId = queryParameters.getThreadId();
-
- boolean isMessageLikePresent = !TextUtils.isEmpty(messageLike);
- boolean isMessageTypeFiltered = (messageType == MESSAGE_TYPE_INCOMING)
- || (messageType == MESSAGE_TYPE_OUTGOING);
- boolean isThreadFiltered = threadId != THREAD_ID_NOT_SET;
-
- if (isMessageLikePresent || isMessageTypeFiltered || isThreadFiltered) {
- rawQuery.append(" WHERE ");
- }
-
- if (messageType == MESSAGE_TYPE_INCOMING) {
- rawQuery.append(MESSAGE_TYPE_COLUMN).append("=").append(MESSAGE_TYPE_INCOMING);
- } else if (messageType == MESSAGE_TYPE_OUTGOING) {
- rawQuery.append(MESSAGE_TYPE_COLUMN).append("=").append(MESSAGE_TYPE_OUTGOING);
- }
-
- if (isMessageLikePresent) {
- if (isMessageTypeFiltered) {
- rawQuery.append(" AND ");
- }
- rawQuery.append(MESSAGE_TEXT_COLUMN).append(" LIKE \"").append(messageLike)
- .append("\"");
- }
-
- if (isThreadFiltered) {
- if (isMessageLikePresent || isMessageTypeFiltered) {
- rawQuery.append(" AND ");
- }
- rawQuery.append(RCS_THREAD_ID_COLUMN).append("=").append(threadId);
- }
-
- // TODO - figure out a way to see if this message has file transfer or not. Ideally we
- // should join the unified table with file transfer table, but using a trigger to change a
- // flag on rcs_message would also work
-
- rawQuery.append(" ORDER BY ");
-
- int sortingProperty = queryParameters.getSortingProperty();
- if (sortingProperty == RcsMessageQueryParams.SORT_BY_TIMESTAMP) {
- rawQuery.append(ORIGINATION_TIMESTAMP_COLUMN);
- } else {
- rawQuery.append(MESSAGE_ID_COLUMN);
- }
-
- rawQuery.append(queryParameters.getSortDirection() ? " ASC " : " DESC ");
-
- RcsProviderUtil.appendLimit(rawQuery, queryParameters.getLimit());
- String rawQueryAsString = rawQuery.toString();
- Cursor cursor = db.rawQuery(rawQueryAsString, null);
-
- // If the query was paginated, build the next query
- int limit = queryParameters.getLimit();
- if (limit > 0) {
- RcsProviderUtil.createContinuationTokenBundle(cursor,
- new RcsQueryContinuationToken(MESSAGE_QUERY_CONTINUATION_TOKEN_TYPE,
- rawQueryAsString, limit, limit), QUERY_CONTINUATION_TOKEN);
- }
-
- return cursor;
- }
-
- Cursor queryUnifiedMessageWithId(Uri uri) {
- return queryUnifiedMessageWithSelection(getMessageIdSelection(uri), null);
- }
-
- Cursor queryUnifiedMessageWithIdInThread(Uri uri) {
- return queryUnifiedMessageWithSelection(getMessageIdSelectionInThreadUri(uri), null);
- }
-
- Cursor queryUnifiedMessageWithSelection(String selection, String[] selectionArgs) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- return db.query(UNIFIED_MESSAGE_VIEW, null, selection, selectionArgs, null, null, null,
- null);
- }
-
- Cursor queryIncomingMessageWithId(Uri uri) {
- return queryIncomingMessageWithSelection(getMessageIdSelection(uri), null);
- }
-
- Cursor queryIncomingMessageWithSelection(String selection, String[] selectionArgs) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- return db.query(UNIFIED_INCOMING_MESSAGE_VIEW, null, selection, selectionArgs, null, null,
- null, null);
- }
-
- Cursor queryOutgoingMessageWithId(Uri uri) {
- return queryOutgoingMessageWithSelection(getMessageIdSelection(uri), null);
- }
-
- Cursor queryOutgoingMessageWithSelection(String selection, String[] selectionArgs) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- return db.query(UNIFIED_OUTGOING_MESSAGE_VIEW, null, selection, selectionArgs, null, null,
- null, null);
- }
-
- Cursor queryAllMessagesOnThread(Uri uri, String selection, String[] selectionArgs) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-
- String appendedSelection = appendThreadIdToSelection(uri, selection);
- return db.query(UNIFIED_MESSAGE_VIEW, null, appendedSelection, null, null, null, null);
- }
-
- Uri insertMessageOnThread(Uri uri, ContentValues valuesParameter, boolean isIncoming,
- boolean is1To1) {
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
- String threadId = RcsProviderThreadHelper.getThreadIdFromUri(uri);
- ContentValues values = new ContentValues(valuesParameter);
- values.put(RCS_THREAD_ID_COLUMN, Integer.parseInt(threadId));
-
- db.beginTransaction();
-
- ContentValues subMessageTableValues = new ContentValues();
- if (isIncoming) {
- subMessageTableValues = getIncomingMessageValues(values);
- }
-
- long rowId;
- try {
- rowId = db.insert(RCS_MESSAGE_TABLE, MESSAGE_ID_COLUMN, values);
- if (rowId == INSERTION_FAILED) {
- return null;
- }
-
- subMessageTableValues.put(MESSAGE_ID_COLUMN, rowId);
- long tempId = db.insert(
- isIncoming ? RCS_INCOMING_MESSAGE_TABLE : RCS_OUTGOING_MESSAGE_TABLE,
- MESSAGE_ID_COLUMN, subMessageTableValues);
- if (tempId == INSERTION_FAILED) {
- return null;
- }
-
- // if the thread is outgoing, insert message deliveries
- if (!isIncoming && !insertMessageDeliveriesForOutgoingMessageCreation(db, tempId,
- threadId)) {
- return null;
- }
-
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
-
- values.remove(RCS_THREAD_ID_COLUMN);
-
- String threadPart = is1To1 ? RCS_1_TO_1_THREAD_URI_PART : RCS_GROUP_THREAD_URI_PART;
- String messagePart = isIncoming ? INCOMING_MESSAGE_URI_PART : OUTGOING_MESSAGE_URI_PART;
-
- return CONTENT_AND_AUTHORITY.buildUpon().appendPath(threadPart).appendPath(threadId).
- appendPath(messagePart).appendPath(Long.toString(rowId)).build();
- }
-
- // Tries to insert deliveries for outgoing message, returns false if it fails.
- private boolean insertMessageDeliveriesForOutgoingMessageCreation(
- SQLiteDatabase dbInTransaction, long messageId, String threadId) {
- try (Cursor participantsInThreadCursor = dbInTransaction.query(
- RCS_PARTICIPANT_THREAD_JUNCTION_TABLE, null, RCS_THREAD_ID_COLUMN + "=?",
- new String[]{threadId}, null, null, null)) {
- if (participantsInThreadCursor == null) {
- return false;
- }
-
- while (participantsInThreadCursor.moveToNext()) {
- String participantId = participantsInThreadCursor.getString(
- participantsInThreadCursor.getColumnIndex(
- RCS_PARTICIPANT_ID_COLUMN));
-
- long insertionRow = insertMessageDelivery(Long.toString(messageId), participantId,
- new ContentValues());
-
- if (insertionRow == INSERTION_FAILED) {
- return false;
- }
- }
- }
- return true;
- }
-
- long insertMessageDelivery(Uri uri, ContentValues values) {
- String messageId = getMessageIdFromUri(uri);
- String participantId = getParticipantIdFromDeliveryUri(uri);
- return insertMessageDelivery(messageId, participantId, values);
- }
-
- private long insertMessageDelivery(String messageId, String participantId,
- ContentValues valuesParameter) {
- ContentValues values = new ContentValues(valuesParameter);
- values.put(MESSAGE_ID_COLUMN, messageId);
- values.put(RCS_PARTICIPANT_ID_COLUMN, participantId);
-
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.insert(RCS_MESSAGE_DELIVERY_TABLE, MESSAGE_ID_COLUMN, values);
- }
-
- int updateDelivery(Uri uri, ContentValues contentValues) {
- String messageId = getMessageIdFromUri(uri);
- String participantId = getParticipantIdFromDeliveryUri(uri);
-
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.update(RCS_MESSAGE_DELIVERY_TABLE, contentValues,
- MESSAGE_ID_COLUMN + "=? AND " + RCS_PARTICIPANT_ID_COLUMN + "=?",
- new String[]{messageId, participantId});
- }
-
- int deleteIncomingMessageWithId(Uri uri) {
- return deleteIncomingMessageWithSelection(getMessageIdSelection(uri), null);
- }
-
- int deleteIncomingMessageWithSelection(String selection, String[] selectionArgs) {
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.delete(RCS_INCOMING_MESSAGE_TABLE, selection, selectionArgs);
- }
-
- int deleteOutgoingMessageWithId(Uri uri) {
- return deleteOutgoingMessageWithSelection(getMessageIdSelection(uri), null);
- }
-
- int deleteOutgoingMessageWithSelection(String selection, String[] selectionArgs) {
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.delete(RCS_OUTGOING_MESSAGE_TABLE, selection, selectionArgs);
- }
-
- int updateIncomingMessage(Uri uri, ContentValues values) {
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
- ContentValues incomingMessageValues = getIncomingMessageValues(values);
-
- int updateCountInIncoming = 0;
- int updateCountInCommon = 0;
- db.beginTransaction();
- if (!incomingMessageValues.isEmpty()) {
- updateCountInIncoming = db.update(RCS_INCOMING_MESSAGE_TABLE, incomingMessageValues,
- getMessageIdSelection(uri), null);
- }
- if (!values.isEmpty()) {
- updateCountInCommon = db.update(RCS_MESSAGE_TABLE, values, getMessageIdSelection(uri),
- null);
- }
- db.setTransactionSuccessful();
- db.endTransaction();
-
- return Math.max(updateCountInIncoming, updateCountInCommon);
- }
-
- int updateOutgoingMessage(Uri uri, ContentValues values) {
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.update(RCS_MESSAGE_TABLE, values, getMessageIdSelection(uri), null);
- }
-
- Cursor queryOutgoingMessageDeliveries(Uri uri) {
- String messageId = getMessageIdFromUri(uri);
-
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- return db.query(RCS_MESSAGE_DELIVERY_TABLE, null, MESSAGE_ID_COLUMN + "=?",
- new String[]{messageId}, null, null, null);
- }
-
- Cursor queryFileTransfer(Uri uri) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- return db.query(RCS_FILE_TRANSFER_TABLE, null, FILE_TRANSFER_ID_COLUMN + "=?",
- new String[]{getFileTransferIdFromUri(uri)}, null, null, null, null);
- }
-
- long insertFileTransferToMessage(Uri uri, ContentValues values) {
- String messageId = getMessageIdFromUri(uri);
- values.put(MESSAGE_ID_COLUMN, messageId);
-
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- long rowId = db.insert(RCS_FILE_TRANSFER_TABLE, MESSAGE_ID_COLUMN, values);
- values.remove(MESSAGE_ID_COLUMN);
-
- if (rowId == INSERTION_FAILED) {
- rowId = TRANSACTION_FAILED;
- }
-
- return rowId;
- }
-
- int deleteFileTransfer(Uri uri) {
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.delete(RCS_FILE_TRANSFER_TABLE, FILE_TRANSFER_ID_COLUMN + "=?",
- new String[]{getFileTransferIdFromUri(uri)});
- }
-
- int updateFileTransfer(Uri uri, ContentValues values) {
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.update(RCS_FILE_TRANSFER_TABLE, values,
- FILE_TRANSFER_ID_COLUMN + "=?", new String[]{getFileTransferIdFromUri(uri)});
- }
-
- /**
- * Removes the incoming message values out of all values and returns as a separate content
- * values object.
- */
- private ContentValues getIncomingMessageValues(ContentValues allValues) {
- ContentValues incomingMessageValues = new ContentValues();
-
- if (allValues.containsKey(SENDER_PARTICIPANT_ID_COLUMN)) {
- incomingMessageValues.put(SENDER_PARTICIPANT_ID_COLUMN,
- allValues.getAsInteger(SENDER_PARTICIPANT_ID_COLUMN));
- allValues.remove(SENDER_PARTICIPANT_ID_COLUMN);
- }
-
- if (allValues.containsKey(ARRIVAL_TIMESTAMP_COLUMN)) {
- incomingMessageValues.put(
- ARRIVAL_TIMESTAMP_COLUMN, allValues.getAsLong(ARRIVAL_TIMESTAMP_COLUMN));
- allValues.remove(ARRIVAL_TIMESTAMP_COLUMN);
- }
-
- if (allValues.containsKey(RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN)) {
- incomingMessageValues.put(
- RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN,
- allValues.getAsLong(RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN));
- allValues.remove(RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN);
- }
-
- return incomingMessageValues;
- }
-
- private String appendThreadIdToSelection(Uri uri, String selection) {
- String threadIdSelection = RCS_THREAD_ID_COLUMN + "=" + getThreadIdFromUri(uri);
-
- if (TextUtils.isEmpty(selection)) {
- return threadIdSelection;
- }
-
- return "(" + selection + ") AND " + threadIdSelection;
- }
-
- private String getMessageIdSelection(Uri uri) {
- return MESSAGE_ID_COLUMN + "=" + getMessageIdFromUri(uri);
- }
-
- private String getMessageIdSelectionInThreadUri(Uri uri) {
- return MESSAGE_ID_COLUMN + "=" + getMessageIdFromThreadUri(uri);
- }
-
- private String getMessageIdFromUri(Uri uri) {
- return uri.getPathSegments().get(MESSAGE_ID_INDEX_IN_URI);
- }
-
- private String getFileTransferIdFromUri(Uri uri) {
- // this works because messages and file transfer uri's have the same indices.
- return getMessageIdFromUri(uri);
- }
-
- private String getParticipantIdFromDeliveryUri(Uri uri) {
- // this works because messages in threads and participants in deliveries have the same
- // indices.
- return getMessageIdFromThreadUri(uri);
- }
-
- private String getMessageIdFromThreadUri(Uri uri) {
- return uri.getPathSegments().get(MESSAGE_ID_INDEX_IN_THREAD_URI);
- }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderParticipantHelper.java b/src/com/android/providers/telephony/RcsProviderParticipantHelper.java
deleted file mode 100644
index ab23d6d..0000000
--- a/src/com/android/providers/telephony/RcsProviderParticipantHelper.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.CanonicalAddressesColumns.ADDRESS;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_URI_PART;
-import static android.provider.Telephony.RcsColumns.RcsParticipantHelpers.RCS_PARTICIPANT_WITH_ADDRESS_VIEW;
-import static android.provider.Telephony.RcsColumns.RcsParticipantHelpers.RCS_PARTICIPANT_WITH_THREAD_VIEW;
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-import static android.telephony.ims.RcsParticipantQueryParams.PARTICIPANT_QUERY_PARAMETERS_KEY;
-
-import static android.telephony.ims.RcsQueryContinuationToken.PARTICIPANT_QUERY_CONTINUATION_TOKEN_TYPE;
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static com.android.providers.telephony.RcsProvider.GROUP_THREAD_URI_PREFIX;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_THREAD_JUNCTION_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.TAG;
-import static com.android.providers.telephony.RcsProviderThreadHelper.getThreadIdFromUri;
-import static com.android.providers.telephony.RcsProviderUtil.INSERTION_FAILED;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.telephony.ims.RcsParticipantQueryParams;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Constants and helpers related to participants for {@link RcsProvider} to keep the code clean.
- *
- * @hide
- */
-class RcsProviderParticipantHelper {
- private static final int PARTICIPANT_ID_INDEX_IN_URI = 1;
- private static final int PARTICIPANT_ID_INDEX_IN_THREAD_URI = 3;
-
- @VisibleForTesting
- public static void createParticipantTables(SQLiteDatabase db) {
- Log.d(TAG, "Creating participant tables");
-
- // create participant tables
- db.execSQL("CREATE TABLE " + RCS_PARTICIPANT_TABLE + " (" +
- RCS_PARTICIPANT_ID_COLUMN + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
- CANONICAL_ADDRESS_ID_COLUMN + " INTEGER ," +
- RCS_ALIAS_COLUMN + " TEXT, " +
- "FOREIGN KEY(" + CANONICAL_ADDRESS_ID_COLUMN + ") "
- + "REFERENCES canonical_addresses(_id)" +
- ");");
-
- db.execSQL("CREATE TABLE " + RCS_PARTICIPANT_THREAD_JUNCTION_TABLE + " (" +
- RCS_THREAD_ID_COLUMN + " INTEGER, " +
- RCS_PARTICIPANT_ID_COLUMN + " INTEGER, " +
- "CONSTRAINT thread_participant PRIMARY KEY("
- + RCS_THREAD_ID_COLUMN + ", " + RCS_PARTICIPANT_ID_COLUMN + "), " +
- "FOREIGN KEY(" + RCS_THREAD_ID_COLUMN
- + ") REFERENCES " + RCS_THREAD_TABLE + "(" + RCS_THREAD_ID_COLUMN + "), " +
- "FOREIGN KEY(" + RCS_PARTICIPANT_ID_COLUMN
- + ") REFERENCES " + RCS_PARTICIPANT_TABLE + "(" + RCS_PARTICIPANT_ID_COLUMN + "))");
-
- // create views
-
- // The following view joins rcs_participant table with canonical_addresses table to add the
- // actual address of a participant in the result.
- db.execSQL("CREATE VIEW " + RCS_PARTICIPANT_WITH_ADDRESS_VIEW + " AS SELECT "
- + "rcs_participant.rcs_participant_id, rcs_participant.canonical_address_id, "
- + "rcs_participant.rcs_alias, canonical_addresses.address FROM rcs_participant "
- + "LEFT JOIN canonical_addresses ON "
- + "rcs_participant.canonical_address_id=canonical_addresses._id");
-
- // The following view is the rcs_participant_with_address_view above, plus the information
- // on which threads this participant contributes to, to enable getting participants of a
- // thread
- db.execSQL("CREATE VIEW " + RCS_PARTICIPANT_WITH_THREAD_VIEW + " AS SELECT "
- + "rcs_participant.rcs_participant_id, rcs_participant.canonical_address_id, "
- + "rcs_participant.rcs_alias, canonical_addresses.address, rcs_thread_participant"
- + ".rcs_thread_id FROM rcs_participant LEFT JOIN canonical_addresses ON "
- + "rcs_participant.canonical_address_id=canonical_addresses._id LEFT JOIN "
- + "rcs_thread_participant ON rcs_participant.rcs_participant_id="
- + "rcs_thread_participant.rcs_participant_id");
-
- // TODO - create indexes for faster querying
- }
-
- private final SQLiteOpenHelper mSqLiteOpenHelper;
-
- RcsProviderParticipantHelper(SQLiteOpenHelper sqLiteOpenHelper) {
- mSqLiteOpenHelper = sqLiteOpenHelper;
- }
-
- Cursor queryParticipant(Bundle bundle) {
- RcsParticipantQueryParams queryParameters = null;
- RcsQueryContinuationToken continuationToken = null;
-
- if (bundle != null) {
- queryParameters = bundle.getParcelable(PARTICIPANT_QUERY_PARAMETERS_KEY);
- continuationToken = bundle.getParcelable(QUERY_CONTINUATION_TOKEN);
- }
-
- if (continuationToken != null) {
- return RcsProviderUtil.performContinuationQuery(mSqLiteOpenHelper.getReadableDatabase(),
- continuationToken);
- }
-
- if (queryParameters == null) {
- queryParameters = new RcsParticipantQueryParams.Builder().build();
- }
-
- return performInitialQuery(queryParameters);
- }
-
- private Cursor performInitialQuery(RcsParticipantQueryParams queryParameters) {
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
- StringBuilder rawQuery = buildInitialRawQuery(queryParameters);
- RcsProviderUtil.appendLimit(rawQuery, queryParameters.getLimit());
- String rawQueryAsString = rawQuery.toString();
- Cursor cursor = db.rawQuery(rawQueryAsString, null);
-
- // If the query was paginated, build the next query
- int limit = queryParameters.getLimit();
- if (limit > 0) {
- RcsProviderUtil.createContinuationTokenBundle(cursor,
- new RcsQueryContinuationToken(PARTICIPANT_QUERY_CONTINUATION_TOKEN_TYPE,
- rawQueryAsString, limit, limit), QUERY_CONTINUATION_TOKEN);
- }
-
- return cursor;
- }
-
- private StringBuilder buildInitialRawQuery(RcsParticipantQueryParams queryParameters) {
- StringBuilder rawQuery = new StringBuilder("SELECT * FROM ");
-
- boolean isThreadFiltered = queryParameters.getThreadId() > 0;
-
- if (isThreadFiltered) {
- rawQuery.append(RCS_PARTICIPANT_WITH_THREAD_VIEW);
- } else {
- rawQuery.append(RCS_PARTICIPANT_WITH_ADDRESS_VIEW);
- }
-
- boolean isAliasFiltered = !TextUtils.isEmpty(queryParameters.getAliasLike());
- boolean isCanonicalAddressFiltered = !TextUtils.isEmpty(
- queryParameters.getCanonicalAddressLike());
-
- if (isAliasFiltered || isCanonicalAddressFiltered || isThreadFiltered) {
- rawQuery.append(" WHERE ");
- }
-
- if (isAliasFiltered) {
- rawQuery.append(RCS_ALIAS_COLUMN).append(" LIKE \"").append(
- queryParameters.getAliasLike()).append("\"");
- }
-
- if (isCanonicalAddressFiltered) {
- if (isAliasFiltered) {
- rawQuery.append(" AND ");
- }
- rawQuery.append(ADDRESS).append(" LIKE \"").append(
- queryParameters.getCanonicalAddressLike()).append("\"");
- }
-
- if (isThreadFiltered) {
- if (isAliasFiltered || isCanonicalAddressFiltered) {
- rawQuery.append(" AND ");
- }
- rawQuery.append(RCS_THREAD_ID_COLUMN).append("=").append(queryParameters.getThreadId());
- }
-
- rawQuery.append(" ORDER BY ");
-
- int sortingProperty = queryParameters.getSortingProperty();
- if (sortingProperty == RcsParticipantQueryParams.SORT_BY_ALIAS) {
- rawQuery.append(RCS_ALIAS_COLUMN);
- } else if (sortingProperty == RcsParticipantQueryParams.SORT_BY_CANONICAL_ADDRESS) {
- rawQuery.append(ADDRESS);
- } else {
- rawQuery.append(RCS_PARTICIPANT_ID_COLUMN);
- }
- rawQuery.append(queryParameters.getSortDirection() ? " ASC " : " DESC ");
-
- return rawQuery;
- }
-
- Cursor queryParticipantWithId(Uri uri, String[] projection) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- return db.query(RCS_PARTICIPANT_WITH_ADDRESS_VIEW, projection,
- getParticipantIdSelection(uri), null, null, null, null);
- }
-
- Cursor queryParticipantIn1To1Thread(Uri uri) {
- String threadId = getThreadIdFromUri(uri);
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-
- return db.rawQuery(
- " SELECT * "
- + "FROM rcs_participant "
- + "WHERE rcs_participant.rcs_participant_id = ("
- + " SELECT rcs_thread_participant.rcs_participant_id "
- + " FROM rcs_thread_participant "
- + " WHERE rcs_thread_participant.rcs_thread_id=" + threadId + ")", null);
- }
-
- Cursor queryParticipantsInGroupThread(Uri uri) {
- String threadId = getThreadIdFromUri(uri);
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-
- return db.rawQuery(" SELECT * "
- + "FROM rcs_participant "
- + "WHERE rcs_participant.rcs_participant_id = ("
- + " SELECT rcs_participant_id "
- + " FROM rcs_thread_participant "
- + " WHERE rcs_thread_id= " + threadId + ")", null);
- }
-
- Cursor queryParticipantInGroupThreadWithId(Uri uri) {
- String threadId = getThreadIdFromUri(uri);
- String participantId = getParticipantIdFromUri(uri);
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-
- return db.rawQuery(" SELECT * "
- + "FROM rcs_participant "
- + "WHERE rcs_participant.rcs_participant_id = ("
- + " SELECT rcs_participant_id "
- + " FROM rcs_thread_participant "
- + " WHERE rcs_thread_id=? AND rcs_participant_id=?)",
- new String[]{threadId, participantId});
- }
-
- long insertParticipant(ContentValues contentValues) {
- if (!contentValues.containsKey(CANONICAL_ADDRESS_ID_COLUMN) || TextUtils.isEmpty(
- contentValues.getAsString(CANONICAL_ADDRESS_ID_COLUMN))) {
- Log.e(TAG,
- "RcsProviderParticipantHelper: Inserting participants without canonical "
- + "address is not supported");
- return TRANSACTION_FAILED;
- }
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- long rowId = db.insert(RCS_PARTICIPANT_TABLE, RCS_PARTICIPANT_ID_COLUMN, contentValues);
- Log.e(TAG, "Inserted participant with rowId=" + rowId);
- if (rowId < 0) {
- return TRANSACTION_FAILED;
- }
- return rowId;
- }
-
- /**
- * Inserts a participant into group thread. This function returns the participant ID instead of
- * the row id in the junction table
- */
- long insertParticipantIntoGroupThread(ContentValues values) {
- if (!values.containsKey(RCS_THREAD_ID_COLUMN) || !values.containsKey(
- RCS_PARTICIPANT_ID_COLUMN)) {
- Log.e(TAG, "RcsProviderParticipantHelper: Cannot insert participant into group.");
- return TRANSACTION_FAILED;
- }
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- long insertedRowId = db.insert(RCS_PARTICIPANT_THREAD_JUNCTION_TABLE,
- RCS_PARTICIPANT_ID_COLUMN,
- values);
-
- if (insertedRowId == INSERTION_FAILED) {
- return TRANSACTION_FAILED;
- }
-
- return values.getAsLong(RCS_PARTICIPANT_ID_COLUMN);
- }
-
- /**
- * Inserts a participant into group thread. This function returns the participant ID instead of
- * the row id in the junction table
- */
- long insertParticipantIntoGroupThreadWithId(Uri uri) {
- String threadId = getThreadIdFromUri(uri);
- String participantId = getParticipantIdFromUri(uri);
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
- ContentValues contentValues = new ContentValues(2);
- contentValues.put(RCS_THREAD_ID_COLUMN, threadId);
- contentValues.put(RCS_PARTICIPANT_ID_COLUMN, participantId);
-
- long insertedRowId = db.insert(
- RCS_PARTICIPANT_THREAD_JUNCTION_TABLE, RCS_PARTICIPANT_ID_COLUMN, contentValues);
-
- if (insertedRowId == INSERTION_FAILED) {
- return TRANSACTION_FAILED;
- }
-
- return Long.parseLong(participantId);
- }
-
- int deleteParticipantWithId(Uri uri) {
- String participantId = uri.getPathSegments().get(PARTICIPANT_ID_INDEX_IN_URI);
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
- // See if this participant is involved in any threads
- Cursor cursor = db.query(RCS_PARTICIPANT_THREAD_JUNCTION_TABLE, null,
- RCS_PARTICIPANT_ID_COLUMN + "=?", new String[]{participantId}, null, null, null);
-
- int participatingThreadCount = 0;
- if (cursor != null) {
- participatingThreadCount = cursor.getCount();
- cursor.close();
- }
-
- if (participatingThreadCount > 0) {
- Log.e(TAG,
- "RcsProviderParticipantHelper: Can't delete participant while it is still in "
- + "RCS threads, uri:"
- + uri);
- return 0;
- }
-
- return db.delete(RCS_PARTICIPANT_TABLE, RCS_PARTICIPANT_ID_COLUMN + "=?",
- new String[]{participantId});
- }
-
- int deleteParticipantFromGroupThread(Uri uri) {
- String threadId = getThreadIdFromUri(uri);
- String participantId = getParticipantIdFromUri(uri);
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- // TODO check to remove owner
- return db.delete(RCS_PARTICIPANT_THREAD_JUNCTION_TABLE,
- RCS_THREAD_ID_COLUMN + "=? AND " + RCS_PARTICIPANT_ID_COLUMN + "=?",
- new String[]{threadId, participantId});
- }
-
- int updateParticipant(ContentValues contentValues, String selection, String[] selectionArgs) {
- if (contentValues.containsKey(RCS_PARTICIPANT_ID_COLUMN)) {
- Log.e(TAG, "RcsProviderParticipantHelper: Updating participant id is not supported");
- return 0;
- }
-
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.update(RCS_PARTICIPANT_TABLE, contentValues, selection, selectionArgs);
- }
-
- int updateParticipantWithId(ContentValues contentValues, Uri uri) {
- return updateParticipant(contentValues, getParticipantIdSelection(uri), null);
- }
-
- private String getParticipantIdSelection(Uri uri) {
- return RCS_PARTICIPANT_ID_COLUMN + "=" + uri.getPathSegments().get(
- PARTICIPANT_ID_INDEX_IN_URI);
- }
-
- Uri getParticipantInThreadUri(ContentValues values, long rowId) {
- if (values == null) {
- return null;
- }
- Integer threadId = values.getAsInteger(RCS_THREAD_ID_COLUMN);
- if (threadId == null) {
- return null;
- }
-
- return GROUP_THREAD_URI_PREFIX.buildUpon().appendPath(
- Integer.toString(threadId)).appendPath(RCS_PARTICIPANT_URI_PART).appendPath(
- Long.toString(rowId)).build();
- }
-
- private String getParticipantIdFromUri(Uri uri) {
- return uri.getPathSegments().get(PARTICIPANT_ID_INDEX_IN_THREAD_URI);
- }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderThreadHelper.java b/src/com/android/providers/telephony/RcsProviderThreadHelper.java
deleted file mode 100644
index c1a35ef..0000000
--- a/src/com/android/providers/telephony/RcsProviderThreadHelper.java
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.RcsColumns.Rcs1To1ThreadColumns.FALLBACK_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.CONFERENCE_URI_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_ICON_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.OWNER_PARTICIPANT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_TEXT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.ORIGINATION_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.STATUS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedThreadColumns.THREAD_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static android.telephony.ims.RcsQueryContinuationToken.THREAD_QUERY_CONTINUATION_TOKEN_TYPE;
-import static android.telephony.ims.RcsThreadQueryParams.THREAD_QUERY_PARAMETERS_KEY;
-
-import static com.android.providers.telephony.RcsProvider.RCS_1_TO_1_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_GROUP_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_MESSAGE_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_THREAD_JUNCTION_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.TAG;
-import static com.android.providers.telephony.RcsProvider.UNIFIED_RCS_THREAD_VIEW;
-import static com.android.providers.telephony.RcsProviderUtil.INSERTION_FAILED;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.BaseColumns;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.telephony.ims.RcsThreadQueryParams;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Constants and helpers related to threads for {@link RcsProvider} to keep the code clean.
- *
- * @hide
- */
-class RcsProviderThreadHelper {
- private static final int THREAD_ID_INDEX_IN_URI = 1;
-
- @VisibleForTesting
- public static void createThreadTables(SQLiteDatabase db) {
- Log.d(TAG, "Creating thread tables");
-
- // Add the thread tables
- db.execSQL("CREATE TABLE " + RCS_THREAD_TABLE + " (" +
- RCS_THREAD_ID_COLUMN + " INTEGER PRIMARY KEY AUTOINCREMENT);");
-
- db.execSQL("CREATE TABLE " + RCS_1_TO_1_THREAD_TABLE + " (" +
- RCS_THREAD_ID_COLUMN + " INTEGER PRIMARY KEY, " +
- FALLBACK_THREAD_ID_COLUMN + " INTEGER, " +
- "FOREIGN KEY(" + RCS_THREAD_ID_COLUMN
- + ") REFERENCES " + RCS_THREAD_TABLE + "(" + RCS_THREAD_ID_COLUMN + ")," +
- "FOREIGN KEY(" + FALLBACK_THREAD_ID_COLUMN
- + ") REFERENCES threads( " + BaseColumns._ID + "))");
-
- db.execSQL("CREATE TABLE " + RCS_GROUP_THREAD_TABLE + " (" +
- RCS_THREAD_ID_COLUMN + " INTEGER PRIMARY KEY, " +
- OWNER_PARTICIPANT_COLUMN + " INTEGER, " +
- GROUP_NAME_COLUMN + " TEXT, " +
- GROUP_ICON_COLUMN + " TEXT, " +
- CONFERENCE_URI_COLUMN + " TEXT, " +
- "FOREIGN KEY(" + RCS_THREAD_ID_COLUMN
- + ") REFERENCES " + RCS_THREAD_TABLE + "(" + RCS_THREAD_ID_COLUMN + "))");
-
- // Add the views
-
- // The following is a unified thread view. Since SQLite does not support right or full
- // joins, we are using a union with null values for unused variables for each thread type.
- // The thread_type column is an easy way to figure out whether the entry came from a 1 to 1
- // thread or a group thread. The last message in each thread is appended to the table
- // entries to figure out the latest threads and snippet text. We use COALESCE so that MAX()
- // can take null values into account in order to have threads with no messages still
- // represented here
- //
- // SELECT <1 to 1 thread and first message>
- // FROM (
- // SELECT *
- // FROM rcs_1_to_1_thread LEFT JOIN rcs_message
- // ON rcs_1_to_1_thread.rcs_thread_id=rcs_message.rcs_thread_id)
- // GROUP BY rcs_thread_id
- // HAVING MAX(COALESCE(origination_timestamp,1))
- //
- // UNION
- // SELECT <group thread and first message>
- // FROM (
- // SELECT *
- // FROM rcs_group_thread LEFT JOIN rcs_message
- // ON rcs_group_thread.rcs_thread_id=rcs_message.rcs_thread_id)
- // GROUP BY rcs_thread_id
- // HAVING MAX(COALESCE(origination_timestamp,1))
-
- db.execSQL("CREATE VIEW " + UNIFIED_RCS_THREAD_VIEW + " AS "
- + "SELECT "
- + RCS_THREAD_ID_COLUMN + ", "
- + FALLBACK_THREAD_ID_COLUMN + ", "
- + "null AS " + OWNER_PARTICIPANT_COLUMN + ", "
- + "null AS " + GROUP_NAME_COLUMN + ", "
- + "null AS " + GROUP_ICON_COLUMN + ", "
- + "null AS " + CONFERENCE_URI_COLUMN + ", "
- + "0 AS " + THREAD_TYPE_COLUMN + ", "
- + ORIGINATION_TIMESTAMP_COLUMN + ", "
- + MESSAGE_TEXT_COLUMN + ", "
- + STATUS_COLUMN
- + " FROM (SELECT * FROM "
- + RCS_1_TO_1_THREAD_TABLE + " LEFT JOIN " + RCS_MESSAGE_TABLE
- + " ON "
- + RCS_1_TO_1_THREAD_TABLE + "." + RCS_THREAD_ID_COLUMN + "="
- + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ")"
- + " GROUP BY " + RCS_THREAD_ID_COLUMN
- + " HAVING MAX(COALESCE("
- + ORIGINATION_TIMESTAMP_COLUMN + ", 1))"
- + " UNION SELECT "
- + RCS_THREAD_ID_COLUMN + ", "
- + "null AS " + FALLBACK_THREAD_ID_COLUMN + ", "
- + OWNER_PARTICIPANT_COLUMN + ", "
- + GROUP_NAME_COLUMN + ", "
- + GROUP_ICON_COLUMN + ", "
- + CONFERENCE_URI_COLUMN + ", "
- + "1 AS " + THREAD_TYPE_COLUMN + ", "
- + ORIGINATION_TIMESTAMP_COLUMN + ", "
- + MESSAGE_TEXT_COLUMN + ", "
- + STATUS_COLUMN
- + " FROM (SELECT * FROM "
- + RCS_GROUP_THREAD_TABLE + " LEFT JOIN " + RCS_MESSAGE_TABLE
- + " ON "
- + RCS_GROUP_THREAD_TABLE + "." + RCS_THREAD_ID_COLUMN + "="
- + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ")"
- + " GROUP BY " + RCS_THREAD_ID_COLUMN
- + " HAVING MAX(COALESCE("
- + ORIGINATION_TIMESTAMP_COLUMN + ", 1))");
-
- // Add the triggers
-
- // Delete the corresponding rcs_thread row upon deleting a row in rcs_1_to_1_thread
- //
- // CREATE TRIGGER deleteRcsThreadAfter1to1
- // AFTER DELETE ON rcs_1_to_1_thread
- // BEGIN
- // DELETE FROM rcs_thread WHERE rcs_thread._id=OLD.rcs_thread_id;
- // END
- db.execSQL("CREATE TRIGGER deleteRcsThreadAfter1to1 AFTER DELETE ON "
- + RCS_1_TO_1_THREAD_TABLE + " BEGIN DELETE FROM " + RCS_THREAD_TABLE + " WHERE "
- + RCS_THREAD_TABLE + "." + RCS_THREAD_ID_COLUMN + "=OLD." + RCS_THREAD_ID_COLUMN
- + "; END");
-
- // Delete the corresponding rcs_thread row upon deleting a row in rcs_group_thread
- //
- // CREATE TRIGGER deleteRcsThreadAfter1to1
- // AFTER DELETE ON rcs_1_to_1_thread
- // BEGIN
- // DELETE FROM rcs_thread WHERE rcs_thread._id=OLD.rcs_thread_id;
- // END
- db.execSQL("CREATE TRIGGER deleteRcsThreadAfterGroup AFTER DELETE ON "
- + RCS_GROUP_THREAD_TABLE + " BEGIN DELETE FROM " + RCS_THREAD_TABLE + " WHERE "
- + RCS_THREAD_TABLE + "." + RCS_THREAD_ID_COLUMN + "=OLD." + RCS_THREAD_ID_COLUMN
- + "; END");
-
- // Delete the junction table entries upon deleting a 1 to 1 thread
- //
- // CREATE TRIGGER delete1To1JunctionEntries
- // AFTER
- // DELETE ON rcs_1_to_1_thread
- // BEGIN
- // DELETE FROM
- // rcs_thread_participant
- // WHERE
- // rcs_thread_participant.rcs_thread_id = OLD.rcs_thread_id;
- // END
- db.execSQL("CREATE TRIGGER delete1To1JunctionEntries AFTER DELETE ON "
- + RCS_1_TO_1_THREAD_TABLE + " BEGIN DELETE FROM "
- + RCS_PARTICIPANT_THREAD_JUNCTION_TABLE + " WHERE "
- + RCS_PARTICIPANT_THREAD_JUNCTION_TABLE + "." + RCS_THREAD_ID_COLUMN + "=OLD."
- + RCS_THREAD_ID_COLUMN + "; END");
-
- // Delete the junction table entries upon deleting a group thread
- //
- // CREATE TRIGGER delete1To1JunctionEntries
- // AFTER
- // DELETE ON rcs_1_to_1_thread
- // BEGIN
- // DELETE FROM
- // rcs_thread_participant
- // WHERE
- // rcs_thread_participant.rcs_thread_id = OLD.rcs_thread_id;
- // END
- db.execSQL("CREATE TRIGGER deleteGroupJunctionEntries AFTER DELETE ON "
- + RCS_GROUP_THREAD_TABLE + " BEGIN DELETE FROM "
- + RCS_PARTICIPANT_THREAD_JUNCTION_TABLE + " WHERE "
- + RCS_PARTICIPANT_THREAD_JUNCTION_TABLE + "." + RCS_THREAD_ID_COLUMN + "=OLD."
- +RCS_THREAD_ID_COLUMN + "; END");
-
- // TODO - delete all messages in a thread after deleting a thread
-
- // TODO - create indexes for faster querying
- }
-
- private final SQLiteOpenHelper mSqLiteOpenHelper;
-
- RcsProviderThreadHelper(SQLiteOpenHelper sqLiteOpenHelper) {
- mSqLiteOpenHelper = sqLiteOpenHelper;
- }
-
- Cursor queryUnifiedThread(Bundle bundle) {
- RcsThreadQueryParams queryParameters = null;
- RcsQueryContinuationToken continuationToken = null;
- if (bundle != null) {
- queryParameters = bundle.getParcelable(
- THREAD_QUERY_PARAMETERS_KEY);
- continuationToken = bundle.getParcelable(QUERY_CONTINUATION_TOKEN);
- }
-
- if (continuationToken != null) {
- return RcsProviderUtil.performContinuationQuery(mSqLiteOpenHelper.getReadableDatabase(),
- continuationToken);
- }
-
- if (queryParameters == null) {
- queryParameters = new RcsThreadQueryParams.Builder().build();
- }
-
- return performInitialQuery(queryParameters);
- }
-
- private Cursor performInitialQuery(RcsThreadQueryParams queryParameters) {
- if (queryParameters == null) {
- // return everything for test purposes
- queryParameters = new RcsThreadQueryParams.Builder().build();
- }
-
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- StringBuilder rawQuery = new StringBuilder("SELECT * FROM ").append(
- UNIFIED_RCS_THREAD_VIEW);
-
- if (queryParameters.getThreadType() == RcsThreadQueryParams.THREAD_TYPE_1_TO_1) {
- rawQuery.append(" WHERE ").append(THREAD_TYPE_COLUMN).append("=0");
- } else if (queryParameters.getThreadType() == RcsThreadQueryParams.THREAD_TYPE_GROUP) {
- rawQuery.append(" WHERE ").append(THREAD_TYPE_COLUMN).append("=1");
- }
-
- rawQuery.append(" ORDER BY ");
-
- if (queryParameters.getSortingProperty() == RcsThreadQueryParams.SORT_BY_TIMESTAMP) {
- rawQuery.append(ORIGINATION_TIMESTAMP_COLUMN);
- } else {
- rawQuery.append(RCS_THREAD_ID_COLUMN);
- }
-
- rawQuery.append(queryParameters.getSortDirection() ? " ASC " : " DESC ");
- RcsProviderUtil.appendLimit(rawQuery, queryParameters.getLimit());
-
- String rawQueryAsString = rawQuery.toString();
- Cursor cursor = db.rawQuery(rawQueryAsString, null);
-
- // If this is a paginated query, build the next query and return as a Cursor extra. Only do
- // this if the current query returned a result.
- int limit = queryParameters.getLimit();
- if (limit > 0) {
- RcsProviderUtil.createContinuationTokenBundle(cursor,
- new RcsQueryContinuationToken(THREAD_QUERY_CONTINUATION_TOKEN_TYPE,
- rawQueryAsString, limit, limit), QUERY_CONTINUATION_TOKEN);
- }
-
- return cursor;
- }
-
- Cursor queryUnifiedThreadUsingId(Uri uri, String[] projection) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- String threadId = getThreadIdFromUri(uri);
-
- return db.query(UNIFIED_RCS_THREAD_VIEW, projection, RCS_THREAD_ID_COLUMN + "=?",
- new String[]{threadId},
- null, null, null);
- }
-
- Cursor query1to1Thread(String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- return db.query(RCS_1_TO_1_THREAD_TABLE, projection, selection, selectionArgs, null,
- null, sortOrder);
- }
-
- Cursor query1To1ThreadUsingId(Uri uri, String[] projection) {
- return query1to1Thread(projection, getThreadIdSelection(uri), null, null);
- }
-
- Cursor queryGroupThread(String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
- return db.query(RCS_GROUP_THREAD_TABLE, projection, selection, selectionArgs, null,
- null, sortOrder);
- }
-
- Cursor queryGroupThreadUsingId(Uri uri, String[] projection) {
- return queryGroupThread(projection, getThreadIdSelection(uri), null, null);
- }
-
- /**
- * @param contentValues should contain the participant ID of the other participant under key
- * {@link RCS_PARTICIPANT_ID_COLUMN}
- */
- long insert1To1Thread(ContentValues contentValues) {
- if (contentValues.containsKey(RCS_THREAD_ID_COLUMN)) {
- Log.e(RcsProvider.TAG,
- "RcsProviderThreadHelper: inserting threads with IDs is not supported");
- return TRANSACTION_FAILED;
- }
-
- Long participantId = contentValues.getAsLong(RCS_PARTICIPANT_ID_COLUMN);
- if (participantId == null) {
- Log.e(RcsProvider.TAG,
- "inserting threads without participant IDs is not supported");
- return TRANSACTION_FAILED;
- }
-
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- try {
- db.beginTransaction();
-
- if (hasExisting1To1ThreadForParticipant(db, participantId)) {
- return TRANSACTION_FAILED;
- }
-
- long threadId = insertIntoCommonRcsThreads(db);
- if (threadId == -1) {
- return TRANSACTION_FAILED;
- }
-
- if (insertP2pThread(db, threadId) == -1) {
- return TRANSACTION_FAILED;
- }
-
- if (insertParticipantIntoP2pThread(db, threadId, participantId) == -1) {
- return TRANSACTION_FAILED;
- }
-
- db.setTransactionSuccessful();
-
- return threadId;
- } finally {
- db.endTransaction();
- }
- }
-
- private long insertP2pThread(SQLiteDatabase db, long threadId) {
- ContentValues contentValues = new ContentValues(1);
- contentValues.put(RCS_THREAD_ID_COLUMN, threadId);
-
- return db.insert(RCS_1_TO_1_THREAD_TABLE, RCS_THREAD_ID_COLUMN, contentValues);
- }
-
- private long insertParticipantIntoP2pThread(
- SQLiteDatabase db, long threadId, long participantId) {
- ContentValues contentValues = new ContentValues(2);
- contentValues.put(RCS_THREAD_ID_COLUMN, threadId);
- contentValues.put(RCS_PARTICIPANT_ID_COLUMN, participantId);
-
- return db.insert(
- RCS_PARTICIPANT_THREAD_JUNCTION_TABLE, RCS_PARTICIPANT_ID_COLUMN, contentValues);
- }
-
- private boolean hasExisting1To1ThreadForParticipant(SQLiteDatabase db, long participantId) {
- String table = joinOnColumn(
- RCS_PARTICIPANT_THREAD_JUNCTION_TABLE,
- RCS_1_TO_1_THREAD_TABLE,
- RCS_THREAD_ID_COLUMN);
-
- try (Cursor cursor = db.query(
- table,
- null,
- RCS_PARTICIPANT_ID_COLUMN + "=?",
- new String[]{Long.toString(participantId)},
- null,
- null,
- null)) {
- if (cursor == null || cursor.getCount() == 0) {
- return false;
- }
- }
-
- return true;
- }
-
- private String joinOnColumn(String t1, String t2, String col) {
- return t1 + " JOIN " + t2 + " ON (" + t1 + "." + col + "=" + t2 + "." + col + ")";
- }
-
- long insertGroupThread(ContentValues contentValues) {
- long returnValue = TRANSACTION_FAILED;
- if (contentValues.containsKey(RCS_THREAD_ID_COLUMN)) {
- Log.e(RcsProvider.TAG,
- "RcsProviderThreadHelper: inserting threads with IDs is not supported");
- return returnValue;
- }
-
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- try {
- db.beginTransaction();
-
- // Insert into the common rcs_threads table
- long rowId = insertIntoCommonRcsThreads(db);
- if (rowId == INSERTION_FAILED) {
- return returnValue;
- }
-
- // Add the rowId in rcs_threads table as a foreign key in rcs_group_table
- contentValues.put(RCS_THREAD_ID_COLUMN, rowId);
- db.insert(RCS_GROUP_THREAD_TABLE, RCS_THREAD_ID_COLUMN, contentValues);
- contentValues.remove(RCS_THREAD_ID_COLUMN);
-
- db.setTransactionSuccessful();
- returnValue = rowId;
- } finally {
- db.endTransaction();
- }
- return returnValue;
- }
-
- private long insertIntoCommonRcsThreads(SQLiteDatabase db) {
- return db.insert(RCS_THREAD_TABLE, RCS_THREAD_ID_COLUMN, new ContentValues());
- }
-
- int delete1To1Thread(String selection, String[] selectionArgs) {
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.delete(RCS_1_TO_1_THREAD_TABLE, selection, selectionArgs);
- }
-
- int delete1To1ThreadWithId(Uri uri) {
- return delete1To1Thread(getThreadIdSelection(uri), null);
- }
-
- int deleteGroupThread(String selection, String[] selectionArgs) {
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.delete(RCS_GROUP_THREAD_TABLE, selection, selectionArgs);
- }
-
- int deleteGroupThreadWithId(Uri uri) {
- return deleteGroupThread(getThreadIdSelection(uri), null);
- }
-
- int update1To1Thread(ContentValues values, String selection, String[] selectionArgs) {
- if (values.containsKey(RCS_THREAD_ID_COLUMN)) {
- Log.e(TAG,
- "RcsProviderThreadHelper: updating thread id for 1 to 1 threads is not "
- + "allowed");
- return 0;
- }
-
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.update(RCS_1_TO_1_THREAD_TABLE, values, selection, selectionArgs);
- }
-
- int update1To1ThreadWithId(ContentValues values, Uri uri) {
- return update1To1Thread(values, getThreadIdSelection(uri), null);
- }
-
- int updateGroupThread(ContentValues values, String selection, String[] selectionArgs) {
- if (values.containsKey(RCS_THREAD_ID_COLUMN)) {
- Log.e(TAG,
- "RcsProviderThreadHelper: updating thread id for group threads is not "
- + "allowed");
- return 0;
- }
-
- SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
- return db.update(RCS_GROUP_THREAD_TABLE, values, selection, selectionArgs);
- }
-
- int updateGroupThreadWithId(ContentValues values, Uri uri) {
- return updateGroupThread(values, getThreadIdSelection(uri), null);
- }
-
- private String getThreadIdSelection(Uri uri) {
- return RCS_THREAD_ID_COLUMN + "=" + getThreadIdFromUri(uri);
- }
-
- static String getThreadIdFromUri(Uri uri) {
- return uri.getPathSegments().get(THREAD_ID_INDEX_IN_URI);
- }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderUtil.java b/src/com/android/providers/telephony/RcsProviderUtil.java
deleted file mode 100644
index 38f7be1..0000000
--- a/src/com/android/providers/telephony/RcsProviderUtil.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static com.android.providers.telephony.RcsProvider.TAG;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.text.TextUtils;
-import android.util.Log;
-
-class RcsProviderUtil {
- /**
- * The value returned when database insertion fails,
- * @see SQLiteDatabase#insert(String, String, ContentValues)
- */
- static final int INSERTION_FAILED = -1;
-
- static void appendLimit(StringBuilder stringBuilder, int limit) {
- if (limit > 0) {
- stringBuilder.append(" LIMIT ").append(limit);
- }
- }
-
- static void createContinuationTokenBundle(Cursor cursor, Parcelable continuationToken,
- String tokenKey) {
- if (cursor.getCount() > 0) {
- Bundle bundle = new Bundle();
- bundle.putParcelable(tokenKey, continuationToken);
- cursor.setExtras(bundle);
- }
- }
-
- /**
- * This method gets a token with raw query, performs the query, increments the token's offset
- * and returns it as a cursor extra
- */
- static Cursor performContinuationQuery(SQLiteDatabase db,
- RcsQueryContinuationToken continuationToken) {
- String rawQuery = continuationToken.getRawQuery();
- int offset = continuationToken.getOffset();
-
- if (offset <= 0 || TextUtils.isEmpty(rawQuery)) {
- Log.e(TAG, "RcsProviderUtil: Invalid continuation token");
- return null;
- }
-
- String continuationQuery = rawQuery + " OFFSET " + offset;
-
- Cursor cursor = db.rawQuery(continuationQuery, null);
- if (cursor.getCount() > 0) {
- continuationToken.incrementOffset();
- Bundle bundle = new Bundle();
- bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
- cursor.setExtras(bundle);
- }
-
- return cursor;
- }
-
- static Uri buildUriWithRowIdAppended(Uri prefix, long rowId) {
- if (rowId == TRANSACTION_FAILED) {
- return null;
- }
- return Uri.withAppendedPath(prefix, Long.toString(rowId));
- }
-
- static Uri returnUriAsIsIfSuccessful(Uri uri, long rowId) {
- if (rowId == TRANSACTION_FAILED) {
- return null;
- }
- return uri;
- }
-}
diff --git a/src/com/android/providers/telephony/ServiceStateProvider.java b/src/com/android/providers/telephony/ServiceStateProvider.java
index afd8fa1..f707200 100644
--- a/src/com/android/providers/telephony/ServiceStateProvider.java
+++ b/src/com/android/providers/telephony/ServiceStateProvider.java
@@ -201,12 +201,12 @@
final int data_reg_state = ss.getDataRegState();
final int voice_roaming_type = ss.getVoiceRoamingType();
final int data_roaming_type = ss.getDataRoamingType();
- final String voice_operator_alpha_long = ss.getVoiceOperatorAlphaLong();
- final String voice_operator_alpha_short = ss.getVoiceOperatorAlphaShort();
- final String voice_operator_numeric = ss.getVoiceOperatorNumeric();
- final String data_operator_alpha_long = ss.getDataOperatorAlphaLong();
- final String data_operator_alpha_short = ss.getDataOperatorAlphaShort();
- final String data_operator_numeric = ss.getDataOperatorNumeric();
+ final String voice_operator_alpha_long = ss.getOperatorAlphaLong();
+ final String voice_operator_alpha_short = ss.getOperatorAlphaShort();
+ final String voice_operator_numeric = ss.getOperatorNumeric();
+ final String data_operator_alpha_long = ss.getOperatorAlphaLong();
+ final String data_operator_alpha_short = ss.getOperatorAlphaShort();
+ final String data_operator_numeric = ss.getOperatorNumeric();
final int is_manual_network_selection = (ss.getIsManualSelection()) ? 1 : 0;
final int ril_voice_radio_technology = ss.getRilVoiceRadioTechnology();
final int ril_data_radio_technology = ss.getRilDataRadioTechnology();
diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java
index e2e6d10..ddfa14c 100644
--- a/src/com/android/providers/telephony/SmsProvider.java
+++ b/src/com/android/providers/telephony/SmsProvider.java
@@ -16,6 +16,8 @@
package com.android.providers.telephony;
+import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
+
import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.ContentProvider;
@@ -75,7 +77,7 @@
// N.B.: These columns must appear in the same order as the
// calls to add appear in convertIccToSms.
"service_center_address", // getServiceCenterAddress
- "address", // getDisplayOriginatingAddress
+ "address", // getDisplayOriginatingAddress or getRecipientAddress
"message_class", // getMessageClass
"body", // getDisplayMessageBody
"date", // getTimestampMillis
@@ -83,9 +85,9 @@
"index_on_icc", // getIndexOnIcc
"is_status_report", // isStatusReportMessage
"transport_type", // Always "sms".
- "type", // Always MESSAGE_TYPE_ALL.
+ "type", // depend on getStatusOnIcc
"locked", // Always 0 (false).
- "error_code", // Always 0
+ "error_code", // Always -1 (NO_ERROR_CODE), previously it was 0 always.
"_id"
};
@@ -292,21 +294,39 @@
}
private Object[] convertIccToSms(SmsMessage message, int id) {
+ int statusOnIcc = message.getStatusOnIcc();
+ int type = Sms.MESSAGE_TYPE_ALL;
+ switch (statusOnIcc) {
+ case SmsManager.STATUS_ON_ICC_READ:
+ case SmsManager.STATUS_ON_ICC_UNREAD:
+ type = Sms.MESSAGE_TYPE_INBOX;
+ break;
+ case SmsManager.STATUS_ON_ICC_SENT:
+ type = Sms.MESSAGE_TYPE_SENT;
+ break;
+ case SmsManager.STATUS_ON_ICC_UNSENT:
+ type = Sms.MESSAGE_TYPE_OUTBOX;
+ break;
+ }
// N.B.: These calls must appear in the same order as the
// columns appear in ICC_COLUMNS.
Object[] row = new Object[13];
row[0] = message.getServiceCenterAddress();
- row[1] = message.getDisplayOriginatingAddress();
+ row[1] =
+ (type == Sms.MESSAGE_TYPE_INBOX)
+ ? message.getDisplayOriginatingAddress()
+ : message.getRecipientAddress();
+
row[2] = String.valueOf(message.getMessageClass());
row[3] = message.getDisplayMessageBody();
row[4] = message.getTimestampMillis();
- row[5] = Sms.STATUS_NONE;
+ row[5] = statusOnIcc;
row[6] = message.getIndexOnIcc();
row[7] = message.isStatusReportMessage();
row[8] = "sms";
- row[9] = TextBasedSmsColumns.MESSAGE_TYPE_ALL;
+ row[9] = type;
row[10] = 0; // locked
- row[11] = 0; // error_code
+ row[11] = NO_ERROR_CODE;
row[12] = id;
return row;
}
@@ -632,7 +652,12 @@
db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
}
if (rowID > 0) {
- Uri uri = Uri.withAppendedPath(url, String.valueOf(rowID));
+ Uri uri = null;
+ if (table == TABLE_SMS) {
+ uri = Uri.withAppendedPath(Sms.CONTENT_URI, String.valueOf(rowID));
+ } else {
+ uri = Uri.withAppendedPath(url, String.valueOf(rowID));
+ }
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.d(TAG, "insert " + uri + " succeeded");
}
diff --git a/src/com/android/providers/telephony/SqlTokenFinder.java b/src/com/android/providers/telephony/SqlTokenFinder.java
deleted file mode 100644
index 9be49fe..0000000
--- a/src/com/android/providers/telephony/SqlTokenFinder.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2019 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
- */
-package com.android.providers.telephony;
-
-import android.annotation.Nullable;
-
-import java.util.function.Consumer;
-
-/**
- * Simple SQL parser to check statements for usage of prohibited/sensitive fields. Mostly copied
- * from
- * packages/providers/ContactsProvider/src/com/android/providers/contacts/sqlite/SqlChecker.java
- */
-public class SqlTokenFinder{
- private static boolean isAlpha(char ch) {
- return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || (ch == '_');
- }
-
- private static boolean isNum(char ch) {
- return ('0' <= ch && ch <= '9');
- }
-
- private static boolean isAlNum(char ch) {
- return isAlpha(ch) || isNum(ch);
- }
-
- private static boolean isAnyOf(char ch, String set) {
- return set.indexOf(ch) >= 0;
- }
-
- private static char peek(String s, int index) {
- return index < s.length() ? s.charAt(index) : '\0';
- }
-
- /**
- * SQL Tokenizer specialized to extract tokens from SQL (snippets).
- *
- * Based on sqlite3GetToken() in tokenzie.c in SQLite.
- *
- * Source for v3.8.6 (which android uses): http://www.sqlite.org/src/artifact/ae45399d6252b4d7
- * (Latest source as of now: http://www.sqlite.org/src/artifact/78c8085bc7af1922)
- *
- * Also draft spec: http://www.sqlite.org/draft/tokenreq.html
- */
- public static void findTokens(@Nullable String sql, Consumer<String> checker) {
- if (sql == null) {
- return;
- }
- int pos = 0;
- final int len = sql.length();
- while (pos < len) {
- final char ch = peek(sql, pos);
-
- // Regular token.
- if (isAlpha(ch)) {
- final int start = pos;
- pos++;
- while (isAlNum(peek(sql, pos))) {
- pos++;
- }
- final int end = pos;
-
- final String token = sql.substring(start, end);
- checker.accept(token);
-
- continue;
- }
-
- // Handle quoted tokens
- if (isAnyOf(ch, "'\"`")) {
- final int quoteStart = pos;
- pos++;
-
- for (;;) {
- pos = sql.indexOf(ch, pos);
- if (pos < 0) {
- throw new IllegalArgumentException("Unterminated quote in" + sql);
- }
- if (peek(sql, pos + 1) != ch) {
- break;
- }
- // Quoted quote char -- e.g. "abc""def" is a single string.
- pos += 2;
- }
- final int quoteEnd = pos;
- pos++;
-
- if (ch != '\'') {
- // Extract the token
- final String tokenUnquoted = sql.substring(quoteStart + 1, quoteEnd);
-
- final String token;
-
- // Unquote if needed. i.e. "aa""bb" -> aa"bb
- if (tokenUnquoted.indexOf(ch) >= 0) {
- token = tokenUnquoted.replaceAll(
- String.valueOf(ch) + ch, String.valueOf(ch));
- } else {
- token = tokenUnquoted;
- }
- checker.accept(token);
- }
- continue;
- }
- // Handle tokens enclosed in [...]
- if (ch == '[') {
- final int quoteStart = pos;
- pos++;
-
- pos = sql.indexOf(']', pos);
- if (pos < 0) {
- throw new IllegalArgumentException("Unterminated quote in" + sql);
- }
- final int quoteEnd = pos;
- pos++;
-
- final String token = sql.substring(quoteStart + 1, quoteEnd);
-
- checker.accept(token);
- continue;
- }
-
- // Detect comments.
- if (ch == '-' && peek(sql, pos + 1) == '-') {
- pos += 2;
- pos = sql.indexOf('\n', pos);
- if (pos < 0) {
- // We disallow strings ending in an inline comment.
- throw new IllegalArgumentException("Unterminated comment in" + sql);
- }
- pos++;
-
- continue;
- }
- if (ch == '/' && peek(sql, pos + 1) == '*') {
- pos += 2;
- pos = sql.indexOf("*/", pos);
- if (pos < 0) {
- throw new IllegalArgumentException("Unterminated comment in" + sql);
- }
- pos += 2;
-
- continue;
- }
-
- // Semicolon is never allowed.
- if (ch == ';') {
- throw new IllegalArgumentException("Semicolon is not allowed in " + sql);
- }
-
- // For this purpose, we can simply ignore other characters.
- // (Note it doesn't handle the X'' literal properly and reports this X as a token,
- // but that should be fine...)
- pos++;
- }
- }
-}
diff --git a/src/com/android/providers/telephony/TelephonyBackupAgent.java b/src/com/android/providers/telephony/TelephonyBackupAgent.java
index 437b5a2..b3c0d99 100644
--- a/src/com/android/providers/telephony/TelephonyBackupAgent.java
+++ b/src/com/android/providers/telephony/TelephonyBackupAgent.java
@@ -319,7 +319,7 @@
final SubscriptionManager subscriptionManager = SubscriptionManager.from(this);
if (subscriptionManager != null) {
final List<SubscriptionInfo> subInfo =
- subscriptionManager.getActiveSubscriptionInfoList(/* userVisibleonly */false);
+ subscriptionManager.getActiveAndHiddenSubscriptionInfoList();
if (subInfo != null) {
for (SubscriptionInfo sub : subInfo) {
final String phoneNumber = getNormalizedNumber(sub);
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index c564a07..b5cd6e9 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -70,6 +70,7 @@
import static android.provider.Telephony.Carriers.WAIT_TIME_RETRY;
import static android.provider.Telephony.Carriers._ID;
+import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -106,20 +107,19 @@
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.text.TextUtils;
-import android.util.EventLog;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.IApnSourceService;
import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.dataconnection.ApnSettingUtils;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.util.XmlUtils;
+import android.service.carrier.IApnSourceService;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -177,6 +177,11 @@
private static final int URL_SIM_APN_LIST_FILTERED = 26;
private static final int URL_SIM_APN_LIST_FILTERED_ID = 27;
+ /**
+ * Default value for mtu if it's not set. Moved from PhoneConstants.
+ */
+ private static final int UNSPECIFIED_INT = -1;
+
private static final String TAG = "TelephonyProvider";
private static final String CARRIERS_TABLE = "carriers";
private static final String CARRIERS_TABLE_TMP = "carriers_tmp";
@@ -207,10 +212,6 @@
private static final String DEFAULT_PROTOCOL = "IP";
private static final String DEFAULT_ROAMING_PROTOCOL = "IP";
- // Used to check if certain queries contain subqueries that may attempt to access sensitive
- // fields in the carriers db.
- private static final String SQL_SELECT_TOKEN = "select";
-
private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final ContentValues s_currentNullMap;
@@ -255,6 +256,8 @@
private boolean mManagedApnEnforced;
+ private static final Map<String, Integer> MVNO_TYPE_STRING_MAP;
+
static {
// Columns not included in UNIQUE constraint: name, current, edited, user, server, password,
// authtype, type, protocol, roaming_protocol, sub_id, modem_cognitive, max_conns,
@@ -291,6 +294,12 @@
CARRIERS_BOOLEAN_FIELDS.add(MODEM_PERSIST);
CARRIERS_BOOLEAN_FIELDS.add(USER_VISIBLE);
CARRIERS_BOOLEAN_FIELDS.add(USER_EDITABLE);
+
+ MVNO_TYPE_STRING_MAP = new ArrayMap<String, Integer>();
+ MVNO_TYPE_STRING_MAP.put("spn", ApnSetting.MVNO_TYPE_SPN);
+ MVNO_TYPE_STRING_MAP.put("imsi", ApnSetting.MVNO_TYPE_IMSI);
+ MVNO_TYPE_STRING_MAP.put("gid", ApnSetting.MVNO_TYPE_GID);
+ MVNO_TYPE_STRING_MAP.put("iccid", ApnSetting.MVNO_TYPE_ICCID);
}
@VisibleForTesting
@@ -484,7 +493,41 @@
}
@VisibleForTesting
- public static class DatabaseHelper extends SQLiteOpenHelper {
+ public static int getVersion(Context context) {
+ if (VDBG) log("getVersion:+");
+ // Get the database version, combining a static schema version and the XML version
+ Resources r = context.getResources();
+ if (r == null) {
+ loge("resources=null, return version=" + Integer.toHexString(DATABASE_VERSION));
+ return DATABASE_VERSION;
+ }
+ XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
+ try {
+ XmlUtils.beginDocument(parser, "apns");
+ int publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
+ int version = DATABASE_VERSION | publicversion;
+ if (VDBG) log("getVersion:- version=0x" + Integer.toHexString(version));
+ return version;
+ } catch (Exception e) {
+ loge("Can't get version of APN database" + e + " return version=" +
+ Integer.toHexString(DATABASE_VERSION));
+ return DATABASE_VERSION;
+ } finally {
+ parser.close();
+ }
+ }
+
+ static public ContentValues setDefaultValue(ContentValues values) {
+ if (!values.containsKey(SUBSCRIPTION_ID)) {
+ int subId = SubscriptionManager.getDefaultSubscriptionId();
+ values.put(SUBSCRIPTION_ID, subId);
+ }
+
+ return values;
+ }
+
+ @VisibleForTesting
+ public class DatabaseHelper extends SQLiteOpenHelper {
// Context to access resources with
private Context mContext;
@@ -501,31 +544,6 @@
setWriteAheadLoggingEnabled(false);
}
- @VisibleForTesting
- public static int getVersion(Context context) {
- if (VDBG) log("getVersion:+");
- // Get the database version, combining a static schema version and the XML version
- Resources r = context.getResources();
- if (r == null) {
- loge("resources=null, return version=" + Integer.toHexString(DATABASE_VERSION));
- return DATABASE_VERSION;
- }
- XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
- try {
- XmlUtils.beginDocument(parser, "apns");
- int publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
- int version = DATABASE_VERSION | publicversion;
- if (VDBG) log("getVersion:- version=0x" + Integer.toHexString(version));
- return version;
- } catch (Exception e) {
- loge("Can't get version of APN database" + e + " return version=" +
- Integer.toHexString(DATABASE_VERSION));
- return DATABASE_VERSION;
- } finally {
- parser.close();
- }
- }
-
@Override
public void onCreate(SQLiteDatabase db) {
if (DBG) log("dbh.onCreate:+ db=" + db);
@@ -605,7 +623,7 @@
return checksum;
}
- private static byte[] toByteArray(InputStream input) throws IOException {
+ private byte[] toByteArray(InputStream input) throws IOException {
byte[] buffer = new byte[128];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
@@ -763,6 +781,8 @@
log("dbh.onUpgrade:+ db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
}
+ deletePreferredApnId(mContext);
+
if (oldVersion < (5 << 16 | 6)) {
// 5 << 16 is the Database version and 6 in the xml version.
@@ -1878,7 +1898,7 @@
e + " for cv " + cv);
// Insertion failed which could be due to a conflict. Check if that is
// the case and merge the entries
- Cursor oldRow = DatabaseHelper.selectConflictingRow(db,
+ Cursor oldRow = selectConflictingRow(db,
CARRIERS_TABLE_TMP, cv);
if (oldRow != null) {
ContentValues mergedValues = new ContentValues();
@@ -2111,15 +2131,6 @@
}
}
- static public ContentValues setDefaultValue(ContentValues values) {
- if (!values.containsKey(SUBSCRIPTION_ID)) {
- int subId = SubscriptionManager.getDefaultSubscriptionId();
- values.put(SUBSCRIPTION_ID, subId);
- }
-
- return values;
- }
-
private void insertAddingDefaults(SQLiteDatabase db, ContentValues row) {
row = setDefaultValue(row);
try {
@@ -2162,264 +2173,264 @@
}
}
}
+ }
- public static void mergeFieldsAndUpdateDb(SQLiteDatabase db, String table, Cursor oldRow,
- ContentValues newRow, ContentValues mergedValues,
- boolean onUpgrade, Context context) {
- if (newRow.containsKey(TYPE)) {
- // Merge the types
- String oldType = oldRow.getString(oldRow.getColumnIndex(TYPE));
- String newType = newRow.getAsString(TYPE);
+ public static void mergeFieldsAndUpdateDb(SQLiteDatabase db, String table, Cursor oldRow,
+ ContentValues newRow, ContentValues mergedValues,
+ boolean onUpgrade, Context context) {
+ if (newRow.containsKey(TYPE)) {
+ // Merge the types
+ String oldType = oldRow.getString(oldRow.getColumnIndex(TYPE));
+ String newType = newRow.getAsString(TYPE);
- if (!oldType.equalsIgnoreCase(newType)) {
- if (oldType.equals("") || newType.equals("")) {
- newRow.put(TYPE, "");
- } else {
- String[] oldTypes = oldType.toLowerCase().split(",");
- String[] newTypes = newType.toLowerCase().split(",");
+ if (!oldType.equalsIgnoreCase(newType)) {
+ if (oldType.equals("") || newType.equals("")) {
+ newRow.put(TYPE, "");
+ } else {
+ String[] oldTypes = oldType.toLowerCase().split(",");
+ String[] newTypes = newType.toLowerCase().split(",");
- if (VDBG) {
- log("mergeFieldsAndUpdateDb: Calling separateRowsNeeded() oldType=" +
- oldType + " old bearer=" + oldRow.getInt(oldRow.getColumnIndex(
- BEARER_BITMASK)) + " old networkType=" +
- oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK)) +
- " old profile_id=" + oldRow.getInt(oldRow.getColumnIndex(
- PROFILE_ID)) + " newRow " + newRow);
- }
-
- // If separate rows are needed, do not need to merge any further
- if (separateRowsNeeded(db, table, oldRow, newRow, context, oldTypes,
- newTypes)) {
- if (VDBG) log("mergeFieldsAndUpdateDb: separateRowsNeeded() returned " +
- "true");
- return;
- }
-
- // Merge the 2 types
- ArrayList<String> mergedTypes = new ArrayList<String>();
- mergedTypes.addAll(Arrays.asList(oldTypes));
- for (String s : newTypes) {
- if (!mergedTypes.contains(s.trim())) {
- mergedTypes.add(s);
- }
- }
- StringBuilder mergedType = new StringBuilder();
- for (int i = 0; i < mergedTypes.size(); i++) {
- mergedType.append((i == 0 ? "" : ",") + mergedTypes.get(i));
- }
- newRow.put(TYPE, mergedType.toString());
+ if (VDBG) {
+ log("mergeFieldsAndUpdateDb: Calling separateRowsNeeded() oldType=" +
+ oldType + " old bearer=" + oldRow.getInt(oldRow.getColumnIndex(
+ BEARER_BITMASK)) + " old networkType=" +
+ oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK)) +
+ " old profile_id=" + oldRow.getInt(oldRow.getColumnIndex(
+ PROFILE_ID)) + " newRow " + newRow);
}
- }
- mergedValues.put(TYPE, newRow.getAsString(TYPE));
- }
- if (newRow.containsKey(BEARER_BITMASK)) {
- int oldBearer = oldRow.getInt(oldRow.getColumnIndex(BEARER_BITMASK));
- int newBearer = newRow.getAsInteger(BEARER_BITMASK);
- if (oldBearer != newBearer) {
- if (oldBearer == 0 || newBearer == 0) {
- newRow.put(BEARER_BITMASK, 0);
- } else {
- newRow.put(BEARER_BITMASK, (oldBearer | newBearer));
+ // If separate rows are needed, do not need to merge any further
+ if (separateRowsNeeded(db, table, oldRow, newRow, context, oldTypes,
+ newTypes)) {
+ if (VDBG) log("mergeFieldsAndUpdateDb: separateRowsNeeded() returned " +
+ "true");
+ return;
}
- }
- mergedValues.put(BEARER_BITMASK, newRow.getAsInteger(BEARER_BITMASK));
- }
- if (newRow.containsKey(NETWORK_TYPE_BITMASK)) {
- int oldBitmask = oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK));
- int newBitmask = newRow.getAsInteger(NETWORK_TYPE_BITMASK);
- if (oldBitmask != newBitmask) {
- if (oldBitmask == 0 || newBitmask == 0) {
- newRow.put(NETWORK_TYPE_BITMASK, 0);
- } else {
- newRow.put(NETWORK_TYPE_BITMASK, (oldBitmask | newBitmask));
+ // Merge the 2 types
+ ArrayList<String> mergedTypes = new ArrayList<String>();
+ mergedTypes.addAll(Arrays.asList(oldTypes));
+ for (String s : newTypes) {
+ if (!mergedTypes.contains(s.trim())) {
+ mergedTypes.add(s);
+ }
}
- }
- mergedValues.put(NETWORK_TYPE_BITMASK, newRow.getAsInteger(NETWORK_TYPE_BITMASK));
- }
-
- if (newRow.containsKey(BEARER_BITMASK)
- && newRow.containsKey(NETWORK_TYPE_BITMASK)) {
- syncBearerBitmaskAndNetworkTypeBitmask(mergedValues);
- }
-
- if (!onUpgrade) {
- // Do not overwrite a carrier or user edit with EDITED=UNEDITED
- if (newRow.containsKey(EDITED_STATUS)) {
- int oldEdited = oldRow.getInt(oldRow.getColumnIndex(EDITED_STATUS));
- int newEdited = newRow.getAsInteger(EDITED_STATUS);
- if (newEdited == UNEDITED && (oldEdited == CARRIER_EDITED
- || oldEdited == CARRIER_DELETED
- || oldEdited == CARRIER_DELETED_BUT_PRESENT_IN_XML
- || oldEdited == USER_EDITED
- || oldEdited == USER_DELETED
- || oldEdited == USER_DELETED_BUT_PRESENT_IN_XML)) {
- newRow.remove(EDITED_STATUS);
+ StringBuilder mergedType = new StringBuilder();
+ for (int i = 0; i < mergedTypes.size(); i++) {
+ mergedType.append((i == 0 ? "" : ",") + mergedTypes.get(i));
}
+ newRow.put(TYPE, mergedType.toString());
}
- mergedValues.putAll(newRow);
}
-
- if (mergedValues.size() > 0) {
- db.update(table, mergedValues, "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")),
- null);
- }
+ mergedValues.put(TYPE, newRow.getAsString(TYPE));
}
- private static boolean separateRowsNeeded(SQLiteDatabase db, String table, Cursor oldRow,
- ContentValues newRow, Context context,
- String[] oldTypes, String[] newTypes) {
- // If this APN falls under persist_apns_for_plmn, and the
- // only difference between old type and new type is that one has dun, and
- // the APNs have profile_id 0 or not set, then set the profile_id to 1 for
- // the dun APN/remove dun from type. This will ensure both oldRow and newRow exist
- // separately in db.
-
- boolean match = false;
-
- // Check if APN falls under persist_apns_for_plmn
- if (context.getResources() != null) {
- String[] persistApnsForPlmns = context.getResources().getStringArray(
- R.array.persist_apns_for_plmn);
- for (String s : persistApnsForPlmns) {
- if (s.equalsIgnoreCase(newRow.getAsString(NUMERIC))) {
- match = true;
- break;
- }
+ if (newRow.containsKey(BEARER_BITMASK)) {
+ int oldBearer = oldRow.getInt(oldRow.getColumnIndex(BEARER_BITMASK));
+ int newBearer = newRow.getAsInteger(BEARER_BITMASK);
+ if (oldBearer != newBearer) {
+ if (oldBearer == 0 || newBearer == 0) {
+ newRow.put(BEARER_BITMASK, 0);
+ } else {
+ newRow.put(BEARER_BITMASK, (oldBearer | newBearer));
}
- } else {
- loge("separateRowsNeeded: resources=null");
+ }
+ mergedValues.put(BEARER_BITMASK, newRow.getAsInteger(BEARER_BITMASK));
+ }
+
+ if (newRow.containsKey(NETWORK_TYPE_BITMASK)) {
+ int oldBitmask = oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK));
+ int newBitmask = newRow.getAsInteger(NETWORK_TYPE_BITMASK);
+ if (oldBitmask != newBitmask) {
+ if (oldBitmask == 0 || newBitmask == 0) {
+ newRow.put(NETWORK_TYPE_BITMASK, 0);
+ } else {
+ newRow.put(NETWORK_TYPE_BITMASK, (oldBitmask | newBitmask));
+ }
+ }
+ mergedValues.put(NETWORK_TYPE_BITMASK, newRow.getAsInteger(NETWORK_TYPE_BITMASK));
+ }
+
+ if (newRow.containsKey(BEARER_BITMASK)
+ && newRow.containsKey(NETWORK_TYPE_BITMASK)) {
+ syncBearerBitmaskAndNetworkTypeBitmask(mergedValues);
+ }
+
+ if (!onUpgrade) {
+ // Do not overwrite a carrier or user edit with EDITED=UNEDITED
+ if (newRow.containsKey(EDITED_STATUS)) {
+ int oldEdited = oldRow.getInt(oldRow.getColumnIndex(EDITED_STATUS));
+ int newEdited = newRow.getAsInteger(EDITED_STATUS);
+ if (newEdited == UNEDITED && (oldEdited == CARRIER_EDITED
+ || oldEdited == CARRIER_DELETED
+ || oldEdited == CARRIER_DELETED_BUT_PRESENT_IN_XML
+ || oldEdited == USER_EDITED
+ || oldEdited == USER_DELETED
+ || oldEdited == USER_DELETED_BUT_PRESENT_IN_XML)) {
+ newRow.remove(EDITED_STATUS);
+ }
+ }
+ mergedValues.putAll(newRow);
+ }
+
+ if (mergedValues.size() > 0) {
+ db.update(table, mergedValues, "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")),
+ null);
+ }
+ }
+
+ private static boolean separateRowsNeeded(SQLiteDatabase db, String table, Cursor oldRow,
+ ContentValues newRow, Context context,
+ String[] oldTypes, String[] newTypes) {
+ // If this APN falls under persist_apns_for_plmn, and the
+ // only difference between old type and new type is that one has dun, and
+ // the APNs have profile_id 0 or not set, then set the profile_id to 1 for
+ // the dun APN/remove dun from type. This will ensure both oldRow and newRow exist
+ // separately in db.
+
+ boolean match = false;
+
+ // Check if APN falls under persist_apns_for_plmn
+ if (context.getResources() != null) {
+ String[] persistApnsForPlmns = context.getResources().getStringArray(
+ R.array.persist_apns_for_plmn);
+ for (String s : persistApnsForPlmns) {
+ if (s.equalsIgnoreCase(newRow.getAsString(NUMERIC))) {
+ match = true;
+ break;
+ }
+ }
+ } else {
+ loge("separateRowsNeeded: resources=null");
+ }
+
+ if (!match) return false;
+
+ // APN falls under persist_apns_for_plmn
+ // Check if only difference between old type and new type is that
+ // one has dun
+ ArrayList<String> oldTypesAl = new ArrayList<String>(Arrays.asList(oldTypes));
+ ArrayList<String> newTypesAl = new ArrayList<String>(Arrays.asList(newTypes));
+ ArrayList<String> listWithDun = null;
+ ArrayList<String> listWithoutDun = null;
+ boolean dunInOld = false;
+ if (oldTypesAl.size() == newTypesAl.size() + 1) {
+ listWithDun = oldTypesAl;
+ listWithoutDun = newTypesAl;
+ dunInOld = true;
+ } else if (oldTypesAl.size() + 1 == newTypesAl.size()) {
+ listWithDun = newTypesAl;
+ listWithoutDun = oldTypesAl;
+ } else {
+ return false;
+ }
+
+ if (listWithDun.contains("dun") && !listWithoutDun.contains("dun")) {
+ listWithoutDun.add("dun");
+ if (!listWithDun.containsAll(listWithoutDun)) {
+ return false;
}
- if (!match) return false;
-
- // APN falls under persist_apns_for_plmn
- // Check if only difference between old type and new type is that
+ // Only difference between old type and new type is that
// one has dun
- ArrayList<String> oldTypesAl = new ArrayList<String>(Arrays.asList(oldTypes));
- ArrayList<String> newTypesAl = new ArrayList<String>(Arrays.asList(newTypes));
- ArrayList<String> listWithDun = null;
- ArrayList<String> listWithoutDun = null;
- boolean dunInOld = false;
- if (oldTypesAl.size() == newTypesAl.size() + 1) {
- listWithDun = oldTypesAl;
- listWithoutDun = newTypesAl;
- dunInOld = true;
- } else if (oldTypesAl.size() + 1 == newTypesAl.size()) {
- listWithDun = newTypesAl;
- listWithoutDun = oldTypesAl;
+ // Check if profile_id is 0/not set
+ if (oldRow.getInt(oldRow.getColumnIndex(PROFILE_ID)) == 0) {
+ if (dunInOld) {
+ // Update oldRow to remove dun from its type field
+ ContentValues updateOldRow = new ContentValues();
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (String s : listWithDun) {
+ if (!s.equalsIgnoreCase("dun")) {
+ sb.append(first ? s : "," + s);
+ first = false;
+ }
+ }
+ String updatedType = sb.toString();
+ if (VDBG) {
+ log("separateRowsNeeded: updating type in oldRow to " + updatedType);
+ }
+ updateOldRow.put(TYPE, updatedType);
+ db.update(table, updateOldRow,
+ "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")), null);
+ return true;
+ } else {
+ if (VDBG) log("separateRowsNeeded: adding profile id 1 to newRow");
+ // Update newRow to set profile_id to 1
+ newRow.put(PROFILE_ID, new Integer(1));
+ }
} else {
return false;
}
- if (listWithDun.contains("dun") && !listWithoutDun.contains("dun")) {
- listWithoutDun.add("dun");
- if (!listWithDun.containsAll(listWithoutDun)) {
- return false;
- }
-
- // Only difference between old type and new type is that
- // one has dun
- // Check if profile_id is 0/not set
- if (oldRow.getInt(oldRow.getColumnIndex(PROFILE_ID)) == 0) {
- if (dunInOld) {
- // Update oldRow to remove dun from its type field
- ContentValues updateOldRow = new ContentValues();
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- for (String s : listWithDun) {
- if (!s.equalsIgnoreCase("dun")) {
- sb.append(first ? s : "," + s);
- first = false;
- }
- }
- String updatedType = sb.toString();
- if (VDBG) {
- log("separateRowsNeeded: updating type in oldRow to " + updatedType);
- }
- updateOldRow.put(TYPE, updatedType);
- db.update(table, updateOldRow,
- "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")), null);
- return true;
- } else {
- if (VDBG) log("separateRowsNeeded: adding profile id 1 to newRow");
- // Update newRow to set profile_id to 1
- newRow.put(PROFILE_ID, new Integer(1));
- }
- } else {
- return false;
- }
-
- // If match was found, both oldRow and newRow need to exist
- // separately in db. Add newRow to db.
- try {
- db.insertWithOnConflict(table, null, newRow, SQLiteDatabase.CONFLICT_REPLACE);
- if (VDBG) log("separateRowsNeeded: added newRow with profile id 1 to db");
- return true;
- } catch (SQLException e) {
- loge("Exception on trying to add new row after updating profile_id");
- }
+ // If match was found, both oldRow and newRow need to exist
+ // separately in db. Add newRow to db.
+ try {
+ db.insertWithOnConflict(table, null, newRow, SQLiteDatabase.CONFLICT_REPLACE);
+ if (VDBG) log("separateRowsNeeded: added newRow with profile id 1 to db");
+ return true;
+ } catch (SQLException e) {
+ loge("Exception on trying to add new row after updating profile_id");
}
-
- return false;
}
- public static Cursor selectConflictingRow(SQLiteDatabase db, String table,
- ContentValues row) {
- // Conflict is possible only when numeric, mcc, mnc (fields without any default value)
- // are set in the new row
- if (!row.containsKey(NUMERIC) || !row.containsKey(MCC) || !row.containsKey(MNC)) {
- loge("dbh.selectConflictingRow: called for non-conflicting row: " + row);
- return null;
- }
+ return false;
+ }
- String[] columns = { "_id",
- TYPE,
- EDITED_STATUS,
- BEARER_BITMASK,
- NETWORK_TYPE_BITMASK,
- PROFILE_ID };
- String selection = TextUtils.join("=? AND ", CARRIERS_UNIQUE_FIELDS) + "=?";
- int i = 0;
- String[] selectionArgs = new String[CARRIERS_UNIQUE_FIELDS.size()];
- for (String field : CARRIERS_UNIQUE_FIELDS) {
- if (!row.containsKey(field)) {
- selectionArgs[i++] = CARRIERS_UNIQUE_FIELDS_DEFAULTS.get(field);
- } else {
- if (CARRIERS_BOOLEAN_FIELDS.contains(field)) {
- // for boolean fields we overwrite the strings "true" and "false" with "1"
- // and "0"
- selectionArgs[i++] = convertStringToIntString(row.getAsString(field));
- } else {
- selectionArgs[i++] = row.getAsString(field);
- }
- }
- }
-
- Cursor c = db.query(table, columns, selection, selectionArgs, null, null, null);
-
- if (c != null) {
- if (c.getCount() == 1) {
- if (VDBG) log("dbh.selectConflictingRow: " + c.getCount() + " conflicting " +
- "row found");
- if (c.moveToFirst()) {
- return c;
- } else {
- loge("dbh.selectConflictingRow: moveToFirst() failed");
- }
- } else {
- loge("dbh.selectConflictingRow: Expected 1 but found " + c.getCount() +
- " matching rows found for cv " + row);
- }
- c.close();
- } else {
- loge("dbh.selectConflictingRow: Error - c is null; no matching row found for " +
- "cv " + row);
- }
-
+ public static Cursor selectConflictingRow(SQLiteDatabase db, String table,
+ ContentValues row) {
+ // Conflict is possible only when numeric, mcc, mnc (fields without any default value)
+ // are set in the new row
+ if (!row.containsKey(NUMERIC) || !row.containsKey(MCC) || !row.containsKey(MNC)) {
+ loge("dbh.selectConflictingRow: called for non-conflicting row: " + row);
return null;
}
+
+ String[] columns = { "_id",
+ TYPE,
+ EDITED_STATUS,
+ BEARER_BITMASK,
+ NETWORK_TYPE_BITMASK,
+ PROFILE_ID };
+ String selection = TextUtils.join("=? AND ", CARRIERS_UNIQUE_FIELDS) + "=?";
+ int i = 0;
+ String[] selectionArgs = new String[CARRIERS_UNIQUE_FIELDS.size()];
+ for (String field : CARRIERS_UNIQUE_FIELDS) {
+ if (!row.containsKey(field)) {
+ selectionArgs[i++] = CARRIERS_UNIQUE_FIELDS_DEFAULTS.get(field);
+ } else {
+ if (CARRIERS_BOOLEAN_FIELDS.contains(field)) {
+ // for boolean fields we overwrite the strings "true" and "false" with "1"
+ // and "0"
+ selectionArgs[i++] = convertStringToIntString(row.getAsString(field));
+ } else {
+ selectionArgs[i++] = row.getAsString(field);
+ }
+ }
+ }
+
+ Cursor c = db.query(table, columns, selection, selectionArgs, null, null, null);
+
+ if (c != null) {
+ if (c.getCount() == 1) {
+ if (VDBG) log("dbh.selectConflictingRow: " + c.getCount() + " conflicting " +
+ "row found");
+ if (c.moveToFirst()) {
+ return c;
+ } else {
+ loge("dbh.selectConflictingRow: moveToFirst() failed");
+ }
+ } else {
+ loge("dbh.selectConflictingRow: Expected 1 but found " + c.getCount() +
+ " matching rows found for cv " + row);
+ }
+ c.close();
+ } else {
+ loge("dbh.selectConflictingRow: Error - c is null; no matching row found for " +
+ "cv " + row);
+ }
+
+ return null;
}
/**
@@ -2546,12 +2557,6 @@
public boolean onCreate() {
mOpenHelper = new DatabaseHelper(getContext());
- try {
- PhoneFactory.addLocalLog(TAG, 100);
- } catch (IllegalArgumentException e) {
- // ignore
- }
-
boolean isNewBuild = false;
String newBuildId = SystemProperties.get("ro.build.id", null);
if (!TextUtils.isEmpty(newBuildId)) {
@@ -2572,25 +2577,6 @@
if (isNewBuild) {
if (!apnSourceServiceExists(getContext())) {
- // Call getReadableDatabase() to make sure onUpgrade is called
- if (VDBG) log("onCreate: calling getReadableDatabase to trigger onUpgrade");
- SQLiteDatabase db = getReadableDatabase();
-
- // Get rid of old preferred apn shared preferences
- SubscriptionManager sm = SubscriptionManager.from(getContext());
- if (sm != null) {
- List<SubscriptionInfo> subInfoList = sm.getAllSubscriptionInfoList();
- for (SubscriptionInfo subInfo : subInfoList) {
- SharedPreferences spPrefFile = getContext().getSharedPreferences(
- PREF_FILE_APN + subInfo.getSubscriptionId(), Context.MODE_PRIVATE);
- if (spPrefFile != null) {
- SharedPreferences.Editor editor = spPrefFile.edit();
- editor.clear();
- editor.apply();
- }
- }
- }
-
// Update APN DB
updateApnDb();
}
@@ -2637,7 +2623,6 @@
private static void localLog(String logMsg) {
Log.d(TAG, logMsg);
- PhoneFactory.localLog(TAG, logMsg);
}
private synchronized boolean isManagedApnEnforced() {
@@ -2701,29 +2686,9 @@
}
}
- private void deletePreferredApnId() {
- SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_APN,
+ private void deletePreferredApnId(Context context) {
+ SharedPreferences sp = context.getSharedPreferences(PREF_FILE_APN,
Context.MODE_PRIVATE);
-
- // Before deleting, save actual preferred apns (not the ids) in a separate SP.
- // NOTE: This code to call setPreferredApn() can be removed since the function is now called
- // from setPreferredApnId(). However older builds (pre oc-mr1) do not have that change, so
- // when devices upgrade from those builds and this function is called, this code is needed
- // otherwise the preferred APN will be lost.
- Map<String, ?> allPrefApnId = sp.getAll();
- for (String key : allPrefApnId.keySet()) {
- // extract subId from key by removing COLUMN_APN_ID
- try {
- int subId = Integer.parseInt(key.replace(COLUMN_APN_ID, ""));
- long apnId = getPreferredApnId(subId, false);
- if (apnId != INVALID_APN_ID) {
- setPreferredApn(apnId, subId);
- }
- } catch (Exception e) {
- loge("Skipping over key " + key + " due to exception " + e);
- }
- }
-
SharedPreferences.Editor editor = sp.edit();
editor.clear();
editor.apply();
@@ -2764,19 +2729,27 @@
private long getPreferredApnIdFromApn(int subId) {
log("getPreferredApnIdFromApn: for subId " + subId);
SQLiteDatabase db = getReadableDatabase();
- String where = TextUtils.join("=? and ", CARRIERS_UNIQUE_FIELDS) + "=?";
- String[] whereArgs = new String[CARRIERS_UNIQUE_FIELDS.size()];
+
+ List<String> whereList = new ArrayList<>();
+ List<String> whereArgsList = new ArrayList<>();
SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
Context.MODE_PRIVATE);
- long apnId = INVALID_APN_ID;
- int i = 0;
for (String key : CARRIERS_UNIQUE_FIELDS) {
- whereArgs[i] = sp.getString(key + subId, null);
- if (whereArgs[i] == null) {
- return INVALID_APN_ID;
+ String value = sp.getString(key + subId, null);
+ if (value == null) {
+ continue;
+ } else {
+ whereList.add(key);
+ whereArgsList.add(value);
}
- i++;
}
+ if (whereList.size() == 0) return INVALID_APN_ID;
+
+ String where = TextUtils.join("=? and ", whereList) + "=?";
+ String[] whereArgs = new String[whereArgsList.size()];
+ whereArgs = whereArgsList.toArray(whereArgs);
+
+ long apnId = INVALID_APN_ID;
Cursor c = db.query(CARRIERS_TABLE, new String[]{"_id"}, where, whereArgs, null, null,
null);
if (c != null) {
@@ -2825,8 +2798,6 @@
String[] selectionArgs, String sort) {
if (VDBG) log("query: url=" + url + ", projectionIn=" + projectionIn + ", selection="
+ selection + "selectionArgs=" + selectionArgs + ", sort=" + sort);
- TelephonyManager mTelephonyManager =
- (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
int subId = SubscriptionManager.getDefaultSubscriptionId();
String subIdString;
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
@@ -2836,7 +2807,7 @@
List<String> constraints = new ArrayList<String>();
int match = s_urlMatcher.match(url);
- checkQueryPermission(match, projectionIn, selection, sort);
+ checkPermission();
switch (match) {
case URL_TELEPHONY_USING_SUBID: {
subIdString = url.getLastPathSegment();
@@ -2847,7 +2818,9 @@
return null;
}
if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
- constraints.add(NUMERIC + " = '" + mTelephonyManager.getSimOperator(subId) + "'");
+ TelephonyManager telephonyManager = getContext()
+ .getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
+ constraints.add(NUMERIC + " = '" + telephonyManager.getSimOperator() + "'");
// TODO b/74213956 turn this back on once insertion includes correct sub id
// constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
}
@@ -3045,97 +3018,35 @@
return ret;
}
- private void checkQueryPermission(int match, String[] projectionIn, String selection,
- String sort) {
- // Determine if we need to do a check for fields in the selection
- boolean selectionOrSortContainsSensitiveFields;
- try {
- selectionOrSortContainsSensitiveFields = containsSensitiveFields(selection);
- selectionOrSortContainsSensitiveFields |= containsSensitiveFields(sort);
- } catch (IllegalArgumentException e) {
- // Malformed sql, check permission anyway and return.
- checkPermission();
- return;
- }
-
- if (selectionOrSortContainsSensitiveFields) {
- try {
- checkPermission();
- } catch (SecurityException e) {
- EventLog.writeEvent(0x534e4554, "124107808", Binder.getCallingUid());
- throw e;
- }
- }
-
- if (match != URL_SIMINFO && match != URL_SIMINFO_USING_SUBID) {
- if (projectionIn != null) {
- for (String column : projectionIn) {
- if (TYPE.equals(column) ||
- MMSC.equals(column) ||
- MMSPROXY.equals(column) ||
- MMSPORT.equals(column) ||
- MVNO_TYPE.equals(column) ||
- MVNO_MATCH_DATA.equals(column) ||
- APN.equals(column)) {
- } else {
- checkPermission();
- break;
- }
- }
- } else {
- // null returns all columns, so need permission check
- checkPermission();
- }
- } else {
- // if querying siminfo, caller should have read privilege permissions
- checkPhonePrivilegePermission();
- }
- }
-
- private boolean containsSensitiveFields(String sqlStatement) {
- try {
- SqlTokenFinder.findTokens(sqlStatement, s -> {
- switch (s.toLowerCase()) {
- case USER:
- case PASSWORD:
- case SQL_SELECT_TOKEN:
- throw new SecurityException();
- }
- });
- } catch (SecurityException e) {
- return true;
- }
- return false;
- }
-
/**
- * To find the current sim APN. Query APN based on {MCC, MNC, MVNO} to support backward
- * compatibility but will move to carrier id in the future.
+ * To find the current sim APN. Query APN based on {MCC, MNC, MVNO} and {Carrier_ID}.
*
* There has three steps:
- * 1. Query the APN based on { MCC, MNC, MVNO }.
- * 2. If can't find the current APN, then query the parent APN. Query based on { MCC, MNC }.
- * 3. else return empty cursor
- *
+ * 1. Query the APN based on { MCC, MNC, MVNO } and if has results jump to step 3, else jump to
+ * step 2.
+ * 2. Fallback to query the parent APN that query based on { MCC, MNC }.
+ * 3. Append the result with the APN that query based on { Carrier_ID }
*/
private Cursor getSubscriptionMatchingAPNList(SQLiteQueryBuilder qb, String[] projectionIn,
String selection, String[] selectionArgs, String sort, int subId) {
Cursor ret;
- final TelephonyManager tm = ((TelephonyManager)
- getContext().getSystemService(Context.TELEPHONY_SERVICE))
+ final TelephonyManager tm = ((TelephonyManager) getContext()
+ .getSystemService(Context.TELEPHONY_SERVICE))
.createForSubscriptionId(subId);
SQLiteDatabase db = getReadableDatabase();
String mccmnc = tm.getSimOperator();
+ int carrierId = tm.getSimCarrierId();
qb.appendWhereStandalone(IS_NOT_USER_DELETED + " and " +
IS_NOT_USER_DELETED_BUT_PRESENT_IN_XML + " and " +
IS_NOT_CARRIER_DELETED + " and " +
IS_NOT_CARRIER_DELETED_BUT_PRESENT_IN_XML);
- // For query db one time, append step 1 and step 2 condition in one selection and
- // separate results after the query is completed. Because IMSI has special match rule,
- // so just query the MCC / MNC and filter the MVNO by ourselves
- qb.appendWhereStandalone(NUMERIC + " = '" + mccmnc + "' ");
+ // For query db one time, append all conditions in one selection and separate results after
+ // the query is completed. IMSI has special match rule, so just query the MCC / MNC and
+ // filter the MVNO by ourselves
+ qb.appendWhereStandalone(NUMERIC + " = '" + mccmnc + "' OR " +
+ CARRIER_ID + " = '" + carrierId + "'");
ret = qb.query(db, null, selection, selectionArgs, null, null, sort);
if (ret == null) {
@@ -3145,13 +3056,15 @@
if (DBG) log("match current APN size: " + ret.getCount());
- String[] coulmnNames = projectionIn != null ? projectionIn : ret.getColumnNames();
- MatrixCursor currentCursor = new MatrixCursor(coulmnNames);
- MatrixCursor parentCursor = new MatrixCursor(coulmnNames);
+ String[] columnNames = projectionIn != null ? projectionIn : ret.getColumnNames();
+ MatrixCursor currentCursor = new MatrixCursor(columnNames);
+ MatrixCursor parentCursor = new MatrixCursor(columnNames);
+ MatrixCursor carrierIdCursor = new MatrixCursor(columnNames);
int numericIndex = ret.getColumnIndex(NUMERIC);
int mvnoIndex = ret.getColumnIndex(MVNO_TYPE);
int mvnoDataIndex = ret.getColumnIndex(MVNO_MATCH_DATA);
+ int carrierIdIndex = ret.getColumnIndex(CARRIER_ID);
IccRecords iccRecords = UiccController.getInstance().getIccRecords(
SubscriptionManager.getPhoneId(subId), UiccController.APP_FAM_3GPP);
@@ -3163,33 +3076,68 @@
//Separate the result into MatrixCursor
while (ret.moveToNext()) {
List<String> data = new ArrayList<>();
- for (String column : coulmnNames) {
+ for (String column : columnNames) {
data.add(ret.getString(ret.getColumnIndex(column)));
}
if (!TextUtils.isEmpty(ret.getString(numericIndex)) &&
ApnSettingUtils.mvnoMatches(iccRecords,
- ApnSetting.getMvnoTypeIntFromString(ret.getString(mvnoIndex)),
+ getMvnoTypeIntFromString(ret.getString(mvnoIndex)),
ret.getString(mvnoDataIndex))) {
- // 1. APN query result based on legacy SIM MCC/MCC and MVNO
+ // 1. The APN that query based on legacy SIM MCC/MCC and MVNO
currentCursor.addRow(data);
- } else if (!TextUtils.isEmpty(ret.getString(numericIndex)) &&
- TextUtils.isEmpty(ret.getString(mvnoIndex))) {
- // 2. APN query result based on SIM MCC/MNC
+ } else if (!TextUtils.isEmpty(ret.getString(numericIndex))
+ && TextUtils.isEmpty(ret.getString(mvnoIndex))) {
+ // 2. The APN that query based on SIM MCC/MNC
parentCursor.addRow(data);
+ } else if (!TextUtils.isEmpty(ret.getString(carrierIdIndex))
+ && ret.getString(carrierIdIndex).equals(String.valueOf(carrierId))) {
+ // The APN that query based on carrier Id (not include the MVNO or MNO APN)
+ carrierIdCursor.addRow(data);
}
}
ret.close();
+ MatrixCursor result;
if (currentCursor.getCount() > 0) {
if (DBG) log("match MVNO APN: " + currentCursor.getCount());
- return currentCursor;
+ result = currentCursor;
} else if (parentCursor.getCount() > 0) {
if (DBG) log("match MNO APN: " + parentCursor.getCount());
- return parentCursor;
+ result = parentCursor;
} else {
- if (DBG) log("APN no match");
- return new MatrixCursor(coulmnNames);
+ if (DBG) log("can't find the MVNO and MNO APN");
+ result = new MatrixCursor(columnNames);
+ }
+
+ if (DBG) log("match carrier id APN: " + carrierIdCursor.getCount());
+ appendCursorData(result, carrierIdCursor);
+ return result;
+ }
+
+ private static void appendCursorData(@NonNull MatrixCursor from, @NonNull MatrixCursor to) {
+ while (to.moveToNext()) {
+ List<Object> data = new ArrayList<>();
+ for (String column : to.getColumnNames()) {
+ int index = to.getColumnIndex(column);
+ switch (to.getType(index)) {
+ case Cursor.FIELD_TYPE_NULL:
+ break;
+ case Cursor.FIELD_TYPE_INTEGER:
+ data.add(to.getInt(index));
+ break;
+ case Cursor.FIELD_TYPE_FLOAT:
+ data.add(to.getFloat(index));
+ break;
+ case Cursor.FIELD_TYPE_BLOB:
+ data.add(to.getBlob(index));
+ break;
+ case Cursor.FIELD_TYPE_STRING:
+ data.add(to.getString(index));
+ break;
+ }
+ }
+ from.addRow(data);
}
}
@@ -3285,10 +3233,10 @@
log("insert: exception " + e);
// Insertion failed which could be due to a conflict. Check if that is the case
// and merge the entries
- Cursor oldRow = DatabaseHelper.selectConflictingRow(db, CARRIERS_TABLE, values);
+ Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, values);
if (oldRow != null) {
ContentValues mergedValues = new ContentValues();
- DatabaseHelper.mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
+ mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
mergedValues, false, getContext());
oldRow.close();
notify = true;
@@ -3331,7 +3279,7 @@
values = new ContentValues();
}
- values = DatabaseHelper.setDefaultValue(values);
+ values = setDefaultValue(values);
if (!values.containsKey(EDITED_STATUS)) {
values.put(EDITED_STATUS, CARRIER_EDITED);
}
@@ -3462,7 +3410,7 @@
case URL_DELETE:
{
// Delete preferred APN for all subIds
- deletePreferredApnId();
+ deletePreferredApnId(getContext());
// Delete unedited entries
count = db.delete(CARRIERS_TABLE, "(" + where + unedited + " and " +
IS_NOT_OWNED_BY_DPC, whereArgs);
@@ -3698,10 +3646,10 @@
// Update failed which could be due to a conflict. Check if that is
// the case and merge the entries
log("update: exception " + e);
- Cursor oldRow = DatabaseHelper.selectConflictingRow(db, CARRIERS_TABLE, values);
+ Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, values);
if (oldRow != null) {
ContentValues mergedValues = new ContentValues();
- DatabaseHelper.mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
+ mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
mergedValues, false, getContext());
oldRow.close();
db.delete(CARRIERS_TABLE, _ID + "=?" + " and " + IS_NOT_OWNED_BY_DPC,
@@ -3933,8 +3881,8 @@
return null;
}
TelephonyManager telephonyManager =
- (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
- String simOperator = telephonyManager.getSimOperator(subId);
+ getContext().getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
+ String simOperator = telephonyManager.getSimOperator();
Cursor cursor = db.query(CARRIERS_TABLE, new String[] {MVNO_TYPE, MVNO_MATCH_DATA},
NUMERIC + "='" + simOperator + "'", null, null, null, DEFAULT_SORT_ORDER);
String where = null;
@@ -3946,7 +3894,7 @@
String mvnoMatchData = cursor.getString(1 /* MVNO_MATCH_DATA index */);
if (!TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData)
&& ApnSettingUtils.mvnoMatches(iccRecords,
- ApnSetting.getMvnoTypeIntFromString(mvnoType), mvnoMatchData)) {
+ getMvnoTypeIntFromString(mvnoType), mvnoMatchData)) {
where = NUMERIC + "='" + simOperator + "'"
+ " AND " + MVNO_TYPE + "='" + mvnoType + "'"
+ " AND " + MVNO_MATCH_DATA + "='" + mvnoMatchData + "'"
@@ -3969,7 +3917,7 @@
@VisibleForTesting
IccRecords getIccRecords(int subId) {
TelephonyManager telephonyManager =
- TelephonyManager.from(getContext()).createForSubscriptionId(subId);
+ getContext().getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
int family = telephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ?
UiccController.APP_FAM_3GPP : UiccController.APP_FAM_3GPP2;
return UiccController.getInstance().getIccRecords(
@@ -3990,7 +3938,7 @@
SQLiteDatabase db = getWritableDatabase();
// Delete preferred APN for all subIds
- deletePreferredApnId();
+ deletePreferredApnId(getContext());
// Delete entries in db
try {
@@ -4093,4 +4041,10 @@
private static void loge(String s) {
Log.e(TAG, s);
}
+
+ private static int getMvnoTypeIntFromString(String mvnoType) {
+ String mvnoTypeString = TextUtils.isEmpty(mvnoType) ? mvnoType : mvnoType.toLowerCase();
+ Integer mvnoTypeInt = MVNO_TYPE_STRING_MAP.get(mvnoTypeString);
+ return mvnoTypeInt == null ? UNSPECIFIED_INT : mvnoTypeInt;
+ }
}
diff --git a/tests/src/com/android/providers/telephony/CellBroadcastProviderTest.java b/tests/src/com/android/providers/telephony/CellBroadcastProviderTest.java
deleted file mode 100644
index b5ff07b..0000000
--- a/tests/src/com/android/providers/telephony/CellBroadcastProviderTest.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 2019 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
- */
-
-package com.android.providers.telephony;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-
-import junit.framework.TestCase;
-
-import android.content.ContentValues;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.Telephony.CellBroadcasts;
-import android.test.mock.MockContentResolver;
-import android.test.mock.MockContext;
-import android.util.Log;
-
-import com.android.providers.telephony.CellBroadcastProvider.PermissionChecker;
-
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-public class CellBroadcastProviderTest extends TestCase {
- private static final String TAG = CellBroadcastProviderTest.class.getSimpleName();
-
- public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts_fwk");
-
- private static final int GEO_SCOPE = 1;
- private static final String PLMN = "123456";
- private static final int LAC = 13;
- private static final int CID = 123;
- private static final int SERIAL_NUMBER = 17984;
- private static final int SERVICE_CATEGORY = 4379;
- private static final String LANGUAGE_CODE = "en";
- private static final String MESSAGE_BODY = "AMBER Alert: xxxx";
- private static final int MESSAGE_FORMAT = 1;
- private static final int MESSAGE_PRIORITY = 3;
- private static final int ETWS_WARNING_TYPE = 1;
- private static final int CMAS_MESSAGE_CLASS = 1;
- private static final int CMAS_CATEGORY = 6;
- private static final int CMAS_RESPONSE_TYPE = 1;
- private static final int CMAS_SEVERITY = 2;
- private static final int CMAS_URGENCY = 3;
- private static final int CMAS_CERTAINTY = 4;
- private static final int RECEIVED_TIME = 1562792637;
- private static final int MESSAGE_BROADCASTED = 1;
- private static final String GEOMETRIES_COORDINATES
- = "polygon|0,0|0,1|1,1|1,0;circle|0,0|100";
-
- private static final String SELECT_BY_ID = CellBroadcasts._ID + "=?";
-
- private static final String[] QUERY_COLUMNS = {
- CellBroadcasts._ID,
- CellBroadcasts.GEOGRAPHICAL_SCOPE,
- CellBroadcasts.PLMN,
- CellBroadcasts.LAC,
- CellBroadcasts.CID,
- CellBroadcasts.SERIAL_NUMBER,
- CellBroadcasts.SERVICE_CATEGORY,
- CellBroadcasts.LANGUAGE_CODE,
- CellBroadcasts.MESSAGE_BODY,
- CellBroadcasts.MESSAGE_FORMAT,
- CellBroadcasts.MESSAGE_PRIORITY,
- CellBroadcasts.ETWS_WARNING_TYPE,
- CellBroadcasts.CMAS_MESSAGE_CLASS,
- CellBroadcasts.CMAS_CATEGORY,
- CellBroadcasts.CMAS_RESPONSE_TYPE,
- CellBroadcasts.CMAS_SEVERITY,
- CellBroadcasts.CMAS_URGENCY,
- CellBroadcasts.CMAS_CERTAINTY,
- CellBroadcasts.RECEIVED_TIME,
- CellBroadcasts.MESSAGE_BROADCASTED,
- CellBroadcasts.GEOMETRIES
- };
-
- private CellBroadcastProviderTestable mCellBroadcastProviderTestable;
- private MockContextWithProvider mContext;
- private MockContentResolver mContentResolver;
-
- @Mock
- private PermissionChecker mMockPermissionChecker;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- MockitoAnnotations.initMocks(this);
- doReturn(true).when(mMockPermissionChecker).hasReadPermission();
- doReturn(true).when(mMockPermissionChecker).hasWritePermission();
-
- mCellBroadcastProviderTestable = new CellBroadcastProviderTestable(mMockPermissionChecker);
- mContext = new MockContextWithProvider(mCellBroadcastProviderTestable);
- mContentResolver = mContext.getContentResolver();
- }
-
- @Override
- protected void tearDown() throws Exception {
- mCellBroadcastProviderTestable.closeDatabase();
- super.tearDown();
- }
-
- @Test
- public void testUpdate() {
- // Insert a cellbroadcast to the database.
- ContentValues cv = fakeCellBroadcast();
- Uri uri = mContentResolver.insert(CONTENT_URI, cv);
- assertThat(uri).isNotNull();
-
- // Change some fields of this cell broadcast.
- int messageBroadcasted = 1 - cv.getAsInteger(CellBroadcasts.MESSAGE_BROADCASTED);
- int receivedTime = 1234555555;
- cv.put(CellBroadcasts.MESSAGE_BROADCASTED, messageBroadcasted);
- cv.put(CellBroadcasts.RECEIVED_TIME, receivedTime);
- mContentResolver.update(CONTENT_URI, cv, SELECT_BY_ID,
- new String[] { uri.getLastPathSegment() });
-
- // Query and check if the update is successed.
- Cursor cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS,
- SELECT_BY_ID, new String[] { uri.getLastPathSegment() }, null /* orderBy */);
- cursor.moveToNext();
-
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME)))
- .isEqualTo(receivedTime);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BROADCASTED)))
- .isEqualTo(messageBroadcasted);
- cursor.close();
- }
-
- @Test
- public void testUpdate_WithoutWritePermission_fail() {
- ContentValues cv = fakeCellBroadcast();
- Uri uri = mContentResolver.insert(CONTENT_URI, cv);
- assertThat(uri).isNotNull();
-
- // Revoke the write permission
- doReturn(false).when(mMockPermissionChecker).hasWritePermission();
-
- try {
- mContentResolver.update(CONTENT_URI, cv, SELECT_BY_ID,
- new String[] { uri.getLastPathSegment() });
- fail();
- } catch (SecurityException ex) {
- // pass the test
- }
- }
-
- @Test
- public void testGetAllCellBroadcast() {
- // Insert some cell broadcasts which message_broadcasted is false
- int messageNotBroadcastedCount = 5;
- ContentValues cv = fakeCellBroadcast();
- cv.put(CellBroadcasts.MESSAGE_BROADCASTED, 0);
- for (int i = 0; i < messageNotBroadcastedCount; i++) {
- mContentResolver.insert(CONTENT_URI, cv);
- }
-
- // Insert some cell broadcasts which message_broadcasted is true
- int messageBroadcastedCount = 6;
- cv.put(CellBroadcasts.MESSAGE_BROADCASTED, 1);
- for (int i = 0; i < messageBroadcastedCount; i++) {
- mContentResolver.insert(CONTENT_URI, cv);
- }
-
- // Query the broadcast with message_broadcasted is false
- Cursor cursor = mContentResolver.query(
- CONTENT_URI,
- QUERY_COLUMNS,
- String.format("%s=?", CellBroadcasts.MESSAGE_BROADCASTED), /* selection */
- new String[] {"0"}, /* selectionArgs */
- null /* sortOrder */);
- assertThat(cursor.getCount()).isEqualTo(messageNotBroadcastedCount);
- }
-
- @Test
- public void testDelete_withoutWritePermission_throwSecurityException() {
- Uri uri = mContentResolver.insert(CONTENT_URI, fakeCellBroadcast());
- assertThat(uri).isNotNull();
-
- // Revoke the write permission
- doReturn(false).when(mMockPermissionChecker).hasWritePermission();
-
- try {
- mContentResolver.delete(CONTENT_URI, SELECT_BY_ID,
- new String[] { uri.getLastPathSegment() });
- fail();
- } catch (SecurityException ex) {
- // pass the test
- }
- }
-
-
- @Test
- public void testDelete_oneRecord_success() {
- // Insert a cellbroadcast to the database.
- ContentValues cv = fakeCellBroadcast();
- Uri uri = mContentResolver.insert(CONTENT_URI, cv);
- assertThat(uri).isNotNull();
-
- String[] selectionArgs = new String[] { uri.getLastPathSegment() };
-
- // Ensure the cell broadcast is inserted.
- Cursor cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS,
- SELECT_BY_ID, selectionArgs, null /* orderBy */);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.close();
-
- // Delete the cell broadcast
- int rowCount = mContentResolver.delete(CONTENT_URI, SELECT_BY_ID,
- selectionArgs);
- assertThat(rowCount).isEqualTo(1);
-
- // Ensure the cell broadcast is deleted.
- cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS, SELECT_BY_ID,
- selectionArgs, null /* orderBy */);
- assertThat(cursor.getCount()).isEqualTo(0);
- cursor.close();
- }
-
- @Test
- public void testDelete_all_success() {
- // Insert a cellbroadcast to the database.
- mContentResolver.insert(CONTENT_URI, fakeCellBroadcast());
- mContentResolver.insert(CONTENT_URI, fakeCellBroadcast());
-
- // Ensure the cell broadcast are inserted.
- Cursor cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS,
- null /* selection */, null /* selectionArgs */, null /* orderBy */);
- assertThat(cursor.getCount()).isEqualTo(2);
- cursor.close();
-
- // Delete all cell broadcasts.
- int rowCount = mContentResolver.delete(
- CONTENT_URI, null /* selection */, null /* selectionArgs */);
- assertThat(rowCount).isEqualTo(2);
- cursor.close();
-
- // Ensure all cell broadcasts are deleted.
- cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS,
- null /* selection */, null /* selectionArgs */, null /* orderBy */);
- assertThat(cursor.getCount()).isEqualTo(0);
- cursor.close();
- }
-
- @Test
- public void testInsert_withoutWritePermission_fail() {
- doReturn(false).when(mMockPermissionChecker).hasWritePermission();
-
- try {
- mContentResolver.insert(CONTENT_URI, fakeCellBroadcast());
- fail();
- } catch (SecurityException ex) {
- // pass the test
- }
- }
-
- @Test
- public void testInsertAndQuery() {
- // Insert a cell broadcast message
- Uri uri = mContentResolver.insert(CONTENT_URI, fakeCellBroadcast());
-
- // Verify that the return uri is not null and the record is inserted into the database
- // correctly.
- assertThat(uri).isNotNull();
- Cursor cursor = mContentResolver.query(
- CONTENT_URI, QUERY_COLUMNS, SELECT_BY_ID,
- new String[] { uri.getLastPathSegment() }, null /* orderBy */);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.GEOGRAPHICAL_SCOPE)))
- .isEqualTo(GEO_SCOPE);
- assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.PLMN)))
- .isEqualTo(PLMN);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.LAC))).isEqualTo(LAC);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CID))).isEqualTo(CID);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SERIAL_NUMBER)))
- .isEqualTo(SERIAL_NUMBER);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SERVICE_CATEGORY)))
- .isEqualTo(SERVICE_CATEGORY);
- assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.LANGUAGE_CODE)))
- .isEqualTo(LANGUAGE_CODE);
- assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BODY)))
- .isEqualTo(MESSAGE_BODY);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_FORMAT)))
- .isEqualTo(MESSAGE_FORMAT);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_PRIORITY)))
- .isEqualTo(MESSAGE_PRIORITY);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.ETWS_WARNING_TYPE)))
- .isEqualTo(ETWS_WARNING_TYPE);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_MESSAGE_CLASS)))
- .isEqualTo(CMAS_MESSAGE_CLASS);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_CATEGORY)))
- .isEqualTo(CMAS_CATEGORY);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_RESPONSE_TYPE)))
- .isEqualTo(CMAS_RESPONSE_TYPE);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_SEVERITY)))
- .isEqualTo(CMAS_SEVERITY);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_URGENCY)))
- .isEqualTo(CMAS_URGENCY);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_CERTAINTY)))
- .isEqualTo(CMAS_CERTAINTY);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME)))
- .isEqualTo(RECEIVED_TIME);
- assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BROADCASTED)))
- .isEqualTo(MESSAGE_BROADCASTED);
- assertThat(cursor.getString(cursor.getColumnIndexOrThrow(
- CellBroadcasts.GEOMETRIES))).isEqualTo(GEOMETRIES_COORDINATES);
- }
-
- /**
- * This is used to give the CellBroadcastProviderTest a mocked context which takes a
- * CellBroadcastProvider and attaches it to the ContentResolver.
- */
- private class MockContextWithProvider extends MockContext {
- private final MockContentResolver mResolver;
-
- public MockContextWithProvider(CellBroadcastProviderTestable cellBroadcastProvider) {
- mResolver = new MockContentResolver();
- cellBroadcastProvider.initializeForTesting(this);
-
- // Add given cellBroadcastProvider to mResolver, so that mResolver can send queries
- // to the provider.
- mResolver.addProvider(CellBroadcastProvider.AUTHORITY, cellBroadcastProvider);
- }
-
- @Override
- public MockContentResolver getContentResolver() {
- return mResolver;
- }
-
-
- @Override
- public Object getSystemService(String name) {
- Log.d(TAG, "getSystemService: returning null");
- return null;
- }
-
- @Override
- public int checkCallingOrSelfPermission(String permission) {
- return PackageManager.PERMISSION_GRANTED;
- }
- }
-
- private static ContentValues fakeCellBroadcast() {
- ContentValues cv = new ContentValues();
- cv.put(CellBroadcasts.GEOGRAPHICAL_SCOPE, GEO_SCOPE);
- cv.put(CellBroadcasts.PLMN, PLMN);
- cv.put(CellBroadcasts.LAC, LAC);
- cv.put(CellBroadcasts.CID, CID);
- cv.put(CellBroadcasts.SERIAL_NUMBER, SERIAL_NUMBER);
- cv.put(CellBroadcasts.SERVICE_CATEGORY, SERVICE_CATEGORY);
- cv.put(CellBroadcasts.LANGUAGE_CODE, LANGUAGE_CODE);
- cv.put(CellBroadcasts.MESSAGE_BODY, MESSAGE_BODY);
- cv.put(CellBroadcasts.MESSAGE_FORMAT, MESSAGE_FORMAT);
- cv.put(CellBroadcasts.MESSAGE_PRIORITY, MESSAGE_PRIORITY);
- cv.put(CellBroadcasts.ETWS_WARNING_TYPE, ETWS_WARNING_TYPE);
- cv.put(CellBroadcasts.CMAS_MESSAGE_CLASS, CMAS_MESSAGE_CLASS);
- cv.put(CellBroadcasts.CMAS_CATEGORY, CMAS_CATEGORY);
- cv.put(CellBroadcasts.CMAS_RESPONSE_TYPE, CMAS_RESPONSE_TYPE);
- cv.put(CellBroadcasts.CMAS_SEVERITY, CMAS_SEVERITY);
- cv.put(CellBroadcasts.CMAS_URGENCY, CMAS_URGENCY);
- cv.put(CellBroadcasts.CMAS_CERTAINTY, CMAS_CERTAINTY);
- cv.put(CellBroadcasts.RECEIVED_TIME, RECEIVED_TIME);
- cv.put(CellBroadcasts.MESSAGE_BROADCASTED, MESSAGE_BROADCASTED);
- cv.put(CellBroadcasts.GEOMETRIES, GEOMETRIES_COORDINATES);
- return cv;
- }
-}
diff --git a/tests/src/com/android/providers/telephony/CellBroadcastProviderTestable.java b/tests/src/com/android/providers/telephony/CellBroadcastProviderTestable.java
deleted file mode 100644
index 8334312..0000000
--- a/tests/src/com/android/providers/telephony/CellBroadcastProviderTestable.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-package com.android.providers.telephony;
-
-import android.content.Context;
-import android.content.pm.ProviderInfo;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-
-public class CellBroadcastProviderTestable extends CellBroadcastProvider {
- private static final String TAG = CellBroadcastProviderTestable.class.getSimpleName();
-
- public CellBroadcastProviderTestable(PermissionChecker permissionChecker) {
- super(permissionChecker);
- }
-
- @Override
- public boolean onCreate() {
- // DO NOT call super.onCreate(), otherwise the permission checker will be override.
- Log.d(TAG, "CellBroadcastProviderTestable onCreate");
- mDbHelper = new InMemoryCellBroadcastProviderDbHelper();
- return true;
- }
-
- public void closeDatabase() {
- mDbHelper.close();
- }
-
- public static class InMemoryCellBroadcastProviderDbHelper extends SQLiteOpenHelper {
- public InMemoryCellBroadcastProviderDbHelper() {
- super(InstrumentationRegistry.getTargetContext(),
- null, // db file name is null for in-memory db
- null, // CursorFactory is null by default
- 1); // db version is no-op for tests
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- Log.d(TAG, "IN MEMORY DB CREATED");
- db.execSQL(getStringForCellBroadcastTableCreation(CELL_BROADCASTS_TABLE_NAME));
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
- }
-
- public void initializeForTesting(Context context) {
- ProviderInfo providerInfo = new ProviderInfo();
- providerInfo.authority = CellBroadcastProvider.AUTHORITY;
-
- // Add context to given carrierIdProvider
- attachInfoForTesting(context, providerInfo);
- }
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderDeleteTest.java b/tests/src/com/android/providers/telephony/RcsProviderDeleteTest.java
deleted file mode 100644
index c0cef0a..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderDeleteTest.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (C) 2018 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
- */
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.OWNER_PARTICIPANT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantEventColumns.NEW_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_NAME_COLUMN;
-
-import static com.android.providers.telephony.RcsProvider.RCS_MESSAGE_TABLE;
-import static com.android.providers.telephony.RcsProviderHelper.setup1To1Thread;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsProviderDeleteTest {
- private MockContentResolver mContentResolver;
- private RcsProviderTestable mRcsProvider;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mRcsProvider = new RcsProviderTestable();
- RcsProviderTestable.MockContextWithProvider
- context = new RcsProviderTestable.MockContextWithProvider(mRcsProvider);
- mContentResolver = context.getContentResolver();
-
- // insert a participant
- // first into the MmsSmsProvider
- mRcsProvider.getWritableDatabase().execSQL(
- "INSERT INTO canonical_addresses VALUES (1, \"+15551234567\")");
-
- // then into the RcsProvider
- ContentValues participantValues = new ContentValues();
- participantValues.put(RCS_ALIAS_COLUMN, "Bob");
- participantValues.put(CANONICAL_ADDRESS_ID_COLUMN, 1);
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/participant"),
- participantValues)).isEqualTo(Uri.parse("content://rcs/participant/1"));
-
- setup1To1Thread(mContentResolver);
-
- // insert one group thread
- ContentValues groupContentValues = new ContentValues();
- groupContentValues.put(OWNER_PARTICIPANT_COLUMN, 1);
- groupContentValues.put(GROUP_NAME_COLUMN, "name");
- Uri groupThreadUri = Uri.parse("content://rcs/group_thread");
- assertThat(mContentResolver.insert(groupThreadUri, groupContentValues)).isEqualTo(
- Uri.parse("content://rcs/group_thread/2"));
-
- Uri addParticipantToGroupThread = Uri.parse("content://rcs/group_thread/2/participant/1");
- assertThat(mContentResolver.insert(addParticipantToGroupThread, null)).isEqualTo(
- addParticipantToGroupThread);
-
- // add incoming and outgoing messages to both threads
- ContentValues messageValues = new ContentValues();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/incoming_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"));
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/p2p_thread/1/outgoing_message/2"));
- assertThat(
- mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/incoming_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/group_thread/2/incoming_message/3"));
- assertThat(
- mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/outgoing_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/group_thread/2/outgoing_message/4"));
-
- // add a file transfer to a message
- ContentValues fileTransferValues = new ContentValues();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/message/3/file_transfer"),
- fileTransferValues)).isEqualTo(Uri.parse("content://rcs/file_transfer/1"));
-
- // insert an alias change event
- ContentValues eventValues = new ContentValues();
- eventValues.put(NEW_ALIAS_COLUMN, "new alias");
- assertThat(
- mContentResolver.insert(Uri.parse("content://rcs/participant/1/alias_change_event"),
- eventValues)).isEqualTo(Uri.parse(
- "content://rcs/participant/1/alias_change_event/1"));
-
- // create a group name change event
- eventValues.clear();
- eventValues.put(NEW_NAME_COLUMN, "new name");
- assertThat(mContentResolver.insert(
- Uri.parse("content://rcs/group_thread/2/name_changed_event"),
- eventValues)).isEqualTo(Uri.parse(
- "content://rcs/group_thread/2/name_changed_event/1"));
- }
-
- @After
- public void tearDown() {
- mRcsProvider.tearDown();
- }
-
- @Test
- public void testDelete1To1ThreadWithId() {
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/p2p_thread/1"), null,
- null)).isEqualTo(1);
- assertDeletionViaQuery("content://rcs/p2p_thread/1");
- }
-
- @Test
- public void testDelete1To1ThreadWithSelection() {
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/p2p_thread"),
- "rcs_fallback_thread_id=1", null)).isEqualTo(1);
- assertDeletionViaQuery("content://rcs/p2p_thread/1");
- }
-
- @Test
- public void testDeleteGroupThreadWithId() {
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/group_thread/2"), null,
- null)).isEqualTo(1);
- assertDeletionViaQuery("content://rcs/group_thread/2");
- }
-
- @Test
- public void testDeleteGroupThreadWithSelection() {
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/group_thread"),
- "group_name=\"name\"", null)).isEqualTo(1);
- assertDeletionViaQuery("content://rcs/group_thread/1");
- }
-
- @Test
- public void testDeleteParticipantWithIdWhileParticipatingInAThread() {
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/participant/1"), null,
- null)).isEqualTo(0);
- }
-
- @Test
- public void testDeleteParticipantAfterLeavingThreads() {
- // leave the first thread
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/group_thread/2/participant/1"),
- null, null)).isEqualTo(1);
-
- // try deleting the participant. It should fail
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/participant/1"), null,
- null)).isEqualTo(0);
-
- // delete the p2p thread
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/p2p_thread/1"), null,
- null)).isEqualTo(1);
-
- // try deleting the participant. It should succeed
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/participant/1"), null,
- null)).isEqualTo(1);
- assertDeletionViaQuery("content://rcs/participant/1");
- }
-
- @Test
- public void testDeleteParticipantWithSelectionFails() {
- assertThat(
- mContentResolver.delete(Uri.parse("content://rcs/participant"), "rcs_alias=\"Bob\"",
- null)).isEqualTo(0);
- }
-
- @Test
- public void testDeleteParticipantFrom1To1ThreadFails() {
- assertThat(
- mContentResolver.delete(Uri.parse("content://rcs/p2p_thread/1/participant/1"), null,
- null)).isEqualTo(0);
- }
-
- @Test
- public void testDeleteParticipantFromGroupThread() {
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/group_thread/2/participant/1"),
- null, null)).isEqualTo(1);
- assertDeletionViaQuery("content://rcs/group_thread/2/participant");
- }
-
- @Test
- public void testDeleteParticipantFromGroupThreadWithSelectionFails() {
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/group_thread/2/participant"),
- "rcs_alias=?", new String[]{"Bob"})).isEqualTo(0);
- }
-
- @Test
- public void testDeleteMessagesUsingUnifiedMessageViewFails() {
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/message/1"), null,
- null)).isEqualTo(0);
- }
-
- @Test
- public void testDeleteMessagesUsingThreadUrisFails() {
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/p2p_thread/1/message/1"), null,
- null)).isEqualTo(0);
- assertThat(
- mContentResolver.delete(Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"),
- null, null)).isEqualTo(0);
- }
-
- @Test
- @Ignore // TODO: fix and un-ignore
- public void testDeleteMessage() {
- // verify there exists 4 messages
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, null,
- null);
- assertThat(cursor.getCount()).isEqualTo(4);
- cursor.close();
-
- // delete 2 of them
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/incoming_message/1"), null,
- null)).isEqualTo(1);
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/outgoing_message/4"), null,
- null)).isEqualTo(1);
-
- // verify that only 2 messages are left
- cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, null, null);
- assertThat(cursor.getCount()).isEqualTo(2);
- cursor.close();
-
- // verify that entries in common table is deleted and only messages with id's 2 and 3 remain
- SQLiteDatabase db = mRcsProvider.getWritableDatabase();
- cursor = db.query(RCS_MESSAGE_TABLE, null, null, null, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(2);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(0)).isEqualTo(2);
- cursor.moveToNext();
- assertThat(cursor.getInt(0)).isEqualTo(3);
- cursor.close();
- }
-
- @Test
- public void testDeleteFileTransfer() {
- assertThat(mContentResolver.delete(Uri.parse("content://rcs/file_transfer/1"), null,
- null)).isEqualTo(1);
- assertDeletionViaQuery("content://rcs/file_transfer/1");
- }
-
- @Test
- public void testDeleteParticipantEvent() {
- assertThat(mContentResolver.delete(Uri.parse(
- "content://rcs/participant/1/alias_change_event/1"), null, null)).isEqualTo(1);
-
- // try deleting again and verify nothing is deleted
- // TODO - convert to query once querying is in place
- assertThat(mContentResolver.delete(Uri.parse(
- "content://rcs/participant/1/alias_change_event/1"), null, null)).isEqualTo(0);
- }
-
- @Test
- public void testDeleteGroupThreadEvent() {
- assertThat(mContentResolver.delete(Uri.parse(
- "content://rcs/group_thread/2/name_changed_event/1"), null, null)).isEqualTo(1);
-
- // try deleting again and verify nothing is deleted
- // TODO - convert to query once querying is in place
- assertThat(mContentResolver.delete(Uri.parse(
- "content://rcs/group_thread/2/name_changed_event/1"), null, null)).isEqualTo(0);
- }
-
- private void assertDeletionViaQuery(String queryUri) {
- Cursor cursor = mContentResolver.query(Uri.parse(queryUri), null, null, null);
- assertThat(cursor.getCount()).isEqualTo(0);
- cursor.close();
- }
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderHelper.java b/tests/src/com/android/providers/telephony/RcsProviderHelper.java
deleted file mode 100644
index 5a7f9a0..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderHelper.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 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
- */
-
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.RcsColumns.Rcs1To1ThreadColumns.FALLBACK_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.net.Uri;
-
-class RcsProviderHelper {
- /**
- * Sets up a 1-to-1 thread with a participant ID of 1 and a fallback thread ID of 1.
- *
- * @return the {@link Uri} of the newly inserted row
- */
- static Uri setup1To1Thread(ContentResolver contentResolver) {
- return setup1To1Thread(contentResolver, 1, 1);
- }
-
- static Uri setup1To1Thread(
- ContentResolver contentResolver, int participantId, int fallbackThreadId) {
- ContentValues insertValues = new ContentValues();
- Uri insertionUri = Uri.parse("content://rcs/p2p_thread");
- insertValues.put(RCS_PARTICIPANT_ID_COLUMN, participantId);
-
- Uri rowUri = contentResolver.insert(insertionUri, insertValues);
- assertThat(rowUri).isNotNull();
-
- ContentValues updateValues = new ContentValues();
- updateValues.put(FALLBACK_THREAD_ID_COLUMN, fallbackThreadId);
- assertThat(contentResolver.update(rowUri, updateValues, null, null))
- .isEqualTo(1);
-
- return rowUri;
- }
-
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderInsertTest.java b/tests/src/com/android/providers/telephony/RcsProviderInsertTest.java
deleted file mode 100644
index 1a48a49..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderInsertTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (C) 2018 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
- */
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.CONFERENCE_URI_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_ICON_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.GLOBAL_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantEventColumns.NEW_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_NAME_COLUMN;
-
-import static com.android.providers.telephony.RcsProviderHelper.setup1To1Thread;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsProviderInsertTest {
- private MockContentResolver mContentResolver;
- private RcsProviderTestable mRcsProvider;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mRcsProvider = new RcsProviderTestable();
- RcsProviderTestable.MockContextWithProvider
- context = new RcsProviderTestable.MockContextWithProvider(mRcsProvider);
- mContentResolver = context.getContentResolver();
- }
-
- @After
- public void tearDown() {
- mRcsProvider.tearDown();
- }
-
- @Test
- public void testInsertUnifiedThreadFails() {
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/thread"), null)).isNull();
- }
-
- @Test
- public void testDuplicate1To1ThreadInsertion() {
- Uri uri = setup1To1Thread(mContentResolver);
-
- assertThat(mContentResolver.insert(uri, null)).isNull();
- }
-
- @Test
- public void testInsertGroupThread() {
- ContentValues contentValues = new ContentValues(3);
- contentValues.put(CONFERENCE_URI_COLUMN, "conference uri");
- contentValues.put(GROUP_NAME_COLUMN, "group name");
- contentValues.put(GROUP_ICON_COLUMN, "groupIcon");
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/group_thread"),
- contentValues)).isEqualTo(Uri.parse("content://rcs/group_thread/1"));
- }
-
- @Test
- public void testInsertParticipant() {
- ContentValues contentValues = new ContentValues();
- contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, 6);
- contentValues.put(RCS_ALIAS_COLUMN, "Alias");
-
- Uri uri = mContentResolver.insert(Uri.parse("content://rcs/participant"), contentValues);
- assertThat(uri).isEqualTo(Uri.parse("content://rcs/participant/1"));
- }
-
- @Test
- public void testInsertParticipantIntoGroupThread() {
- // create a participant
- ContentValues contentValues = new ContentValues();
- contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, 23);
- mContentResolver.insert(Uri.parse("content://rcs/participant"), contentValues);
-
- // create a thread
- ContentValues values = new ContentValues(1);
- values.put(GROUP_NAME_COLUMN, "Group");
- mContentResolver.insert(Uri.parse("content://rcs/group_thread"), values);
-
- // add participant to the thread
- Uri uri = Uri.parse("content://rcs/group_thread/1/participant/1");
- assertThat(mContentResolver.insert(uri, null)).isEqualTo(uri);
-
- // assert that adding again fails
- assertThat(mContentResolver.insert(uri, null)).isNull();
- }
-
- @Test
- public void testInsertMessageFails() {
- ContentValues contentValues = new ContentValues();
- contentValues.put(GLOBAL_ID_COLUMN, "global RCS id");
-
- // try inserting messages without threads
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/message"),
- contentValues)).isNull();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/message/6"),
- contentValues)).isNull();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/incoming_message"),
- contentValues)).isNull();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/incoming_message/12"),
- contentValues)).isNull();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/outgoing_message"),
- contentValues)).isNull();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/outgoing_message/18"),
- contentValues)).isNull();
-
- // try inserting into unified thread view
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/thread/5/incoming_message"),
- contentValues)).isNull();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/thread/5/outgoing_message"),
- contentValues)).isNull();
- }
-
- @Test
- @Ignore // TODO: fix and un-ignore
- public void testInsertMessageIntoThread() {
- // create two threads
- setup1To1Thread(mContentResolver);
- ContentValues values = new ContentValues();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/group_thread"),
- values)).isNotNull();
-
- // add messages to threads
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/incoming_message"),
- values)).isEqualTo(Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"));
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
- values)).isEqualTo(Uri.parse("content://rcs/p2p_thread/1/outgoing_message/2"));
- assertThat(
- mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/incoming_message"),
- values)).isEqualTo(
- Uri.parse("content://rcs/group_thread/2/incoming_message/3"));
- assertThat(
- mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/outgoing_message"),
- values)).isEqualTo(
- Uri.parse("content://rcs/group_thread/2/outgoing_message/4"));
-
- // assert that they are accessible in messages table
- Cursor messageCursor = mContentResolver.query(Uri.parse("content://rcs/message"), null,
- null, null, null);
- assertThat(messageCursor.getCount()).isEqualTo(4);
- }
-
- @Test
- public void testInsertMessageDelivery() {
- setup1To1Thread(mContentResolver);
-
- ContentValues values = new ContentValues();
-
- // add an outgoing message to the thread
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
- values)).isEqualTo(Uri.parse("content://rcs/p2p_thread/1/outgoing_message/1"));
-
- // add a delivery to the outgoing message
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/outgoing_message/1/delivery/1"),
- values)).isEqualTo(Uri.parse("content://rcs/outgoing_message/1/delivery/1"));
- }
-
- @Test
- public void testInsertFileTransfer() {
- setup1To1Thread(mContentResolver);
-
- ContentValues values = new ContentValues();
-
- // add an outgoing message to the thread
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
- values)).isEqualTo(Uri.parse("content://rcs/p2p_thread/1/outgoing_message/1"));
-
- // add a file transfer to the message
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/message/1/file_transfer"),
- values)).isEqualTo(Uri.parse("content://rcs/file_transfer/1"));
- }
-
- @Test
- public void testInsertParticipantEvent() {
- // create a participant
- ContentValues contentValues = new ContentValues();
- contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, 23);
- mContentResolver.insert(Uri.parse("content://rcs/participant"), contentValues);
-
- // insert an alias change event
- ContentValues eventValues = new ContentValues();
- eventValues.put(NEW_ALIAS_COLUMN, "new alias");
- assertThat(
- mContentResolver.insert(Uri.parse("content://rcs/participant/1/alias_change_event"),
- eventValues)).isEqualTo(Uri.parse(
- "content://rcs/participant/1/alias_change_event/1"));
- }
-
- @Test
- public void testInsertGroupThreadEvent() {
- // create a group thread
- ContentValues contentValues = new ContentValues();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/group_thread"),
- contentValues)).isEqualTo(Uri.parse("content://rcs/group_thread/1"));
-
- // create a group name change event
- ContentValues eventValues = new ContentValues();
- eventValues.put(NEW_NAME_COLUMN, "new name");
- assertThat(mContentResolver.insert(
- Uri.parse("content://rcs/group_thread/1/name_changed_event"),
- eventValues)).isEqualTo(Uri.parse(
- "content://rcs/group_thread/1/name_changed_event/1"));
- }
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderQueryTest.java b/tests/src/com/android/providers/telephony/RcsProviderQueryTest.java
deleted file mode 100644
index f0579ea..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderQueryTest.java
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * Copyright (C) 2018 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
- */
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_JOINED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.FILE_SIZE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.SESSION_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_TEXT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.ORIGINATION_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.DESTINATION_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.EVENT_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.SOURCE_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedThreadColumns.THREAD_TYPE_COLUMN;
-import static android.telephony.ims.RcsEventQueryParams.EVENT_QUERY_PARAMETERS_KEY;
-import static android.telephony.ims.RcsEventQueryParams.GROUP_THREAD_NAME_CHANGED_EVENT;
-import static android.telephony.ims.RcsMessageQueryParams.MESSAGE_QUERY_PARAMETERS_KEY;
-import static android.telephony.ims.RcsParticipantQueryParams.PARTICIPANT_QUERY_PARAMETERS_KEY;
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static android.telephony.ims.RcsThreadQueryParams.THREAD_QUERY_PARAMETERS_KEY;
-
-import static com.android.providers.telephony.RcsProviderHelper.setup1To1Thread;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.telephony.ims.RcsEventQueryParams;
-import android.telephony.ims.RcsGroupThread;
-import android.telephony.ims.RcsMessageQueryParams;
-import android.telephony.ims.RcsParticipantQueryParams;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.telephony.ims.RcsThreadQueryParams;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.providers.telephony.RcsProviderTestable.MockContextWithProvider;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsProviderQueryTest {
- private MockContentResolver mContentResolver;
- private RcsProviderTestable mRcsProvider;
-
- private static final String GROUP_NAME = "group name";
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mRcsProvider = new RcsProviderTestable();
- MockContextWithProvider context = new MockContextWithProvider(mRcsProvider);
- mContentResolver = context.getContentResolver();
-
- // insert two participants
- Uri participantUri = Uri.parse("content://rcs/participant");
- ContentValues contentValues = new ContentValues();
- contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, 99);
- contentValues.put(RCS_ALIAS_COLUMN, "Some alias");
- mContentResolver.insert(participantUri, contentValues);
-
- contentValues.clear();
- contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, 100);
- contentValues.put(RCS_ALIAS_COLUMN, "Some other alias");
- mContentResolver.insert(participantUri, contentValues);
-
- // insert two 1 to 1 threads
- setup1To1Thread(mContentResolver, 1, 1);
- setup1To1Thread(mContentResolver, 2, 2);
-
- // insert one group thread
- ContentValues groupContentValues = new ContentValues(1);
- groupContentValues.put(GROUP_NAME_COLUMN, GROUP_NAME);
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/group_thread"),
- groupContentValues)).isEqualTo(Uri.parse("content://rcs/group_thread/3"));
-
- // put participants into the group
- mContentResolver.insert(Uri.parse("content://rcs/group_thread/3/participant/1"), null);
- mContentResolver.insert(Uri.parse("content://rcs/group_thread/3/participant/2"), null);
-
- // insert two messages into first thread, leave the second one empty, insert one into group
- // thread
- ContentValues messageValues = new ContentValues();
-
- messageValues.put(ORIGINATION_TIMESTAMP_COLUMN, 300);
- messageValues.put(MESSAGE_TEXT_COLUMN, "Old message");
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/incoming_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"));
-
- messageValues.clear();
- messageValues.put(ORIGINATION_TIMESTAMP_COLUMN, 400);
- messageValues.put(MESSAGE_TEXT_COLUMN, "New message");
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/p2p_thread/1/outgoing_message/2"));
-
- messageValues.clear();
- messageValues.put(ORIGINATION_TIMESTAMP_COLUMN, 200);
- messageValues.put(MESSAGE_TEXT_COLUMN, "Group message");
- assertThat(
- mContentResolver.insert(Uri.parse("content://rcs/group_thread/3/incoming_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/group_thread/3/incoming_message/3"));
-
- // Add two events to the group thread
- ContentValues eventValues = new ContentValues();
- eventValues.put(NEW_NAME_COLUMN, "New group name");
- assertThat(mContentResolver.insert(
- Uri.parse("content://rcs/group_thread/3/name_changed_event"),
- eventValues)).isEqualTo(
- Uri.parse("content://rcs/group_thread/3/name_changed_event/1"));
-
- eventValues.clear();
- eventValues.put(SOURCE_PARTICIPANT_ID_COLUMN, 1);
- eventValues.put(DESTINATION_PARTICIPANT_ID_COLUMN, 2);
- assertThat(mContentResolver.insert(
- Uri.parse("content://rcs/group_thread/3/participant_joined_event"),
- eventValues)).isEqualTo(
- Uri.parse("content://rcs/group_thread/3/participant_joined_event/2"));
- }
-
- @After
- public void tearDown() {
- mRcsProvider.tearDown();
- }
-
- @Test
- public void testCanQueryUnifiedThreads() {
- RcsThreadQueryParams queryParameters = new RcsThreadQueryParams.Builder().build();
- Bundle bundle = new Bundle();
- bundle.putParcelable(THREAD_QUERY_PARAMETERS_KEY, queryParameters);
-
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/thread"),
- null, bundle, null);
- assertThat(cursor.getCount()).isEqualTo(3);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(1);
- assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(
- GROUP_NAME);
- assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
- 200);
- assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
- "Group message");
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(0);
- assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(null);
- assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(0);
- assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(null);
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(0);
- assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(null);
- assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
- 400);
- assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
- "New message");
- }
-
- @Test
- public void testCanQueryUnifiedThreadsWithLimitAndSorting() {
- RcsThreadQueryParams queryParameters = new RcsThreadQueryParams.Builder()
- .setThreadType(RcsThreadQueryParams.THREAD_TYPE_1_TO_1).setResultLimit(1)
- .setSortProperty(RcsThreadQueryParams.SORT_BY_TIMESTAMP).setSortDirection(true)
- .build();
- Bundle bundle = new Bundle();
- bundle.putParcelable(THREAD_QUERY_PARAMETERS_KEY, queryParameters);
-
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/thread"),
- null, bundle, null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(0);
- assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(null);
- assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(0);
- assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(null);
- }
-
- @Test
- public void testCanContinueThreadQuery() {
- // Limit results to 1.
- RcsThreadQueryParams queryParameters =
- new RcsThreadQueryParams.Builder().setResultLimit(1).build();
- Bundle bundle = new Bundle();
- bundle.putParcelable(THREAD_QUERY_PARAMETERS_KEY, queryParameters);
-
- // Perform an initial query, verify first thread is returned
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/thread"), null, bundle,
- null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(1);
- assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(
- GROUP_NAME);
- assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
- 200);
- assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
- "Group message");
-
- // Put the continuation token in the bundle to do a follow up query
- RcsQueryContinuationToken continuationToken = cursor.getExtras().getParcelable(
- QUERY_CONTINUATION_TOKEN);
- bundle.clear();
- bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
- cursor.close();
-
- cursor = mContentResolver.query(Uri.parse("content://rcs/thread"), null, bundle,
- null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(0);
- assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(null);
- assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(0);
- assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(null);
- cursor.close();
-
- // Put the continuation token in the bundle to do a follow up query again, verify third
- // thread is returned
- continuationToken = cursor.getExtras().getParcelable(QUERY_CONTINUATION_TOKEN);
- bundle.clear();
- bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
- cursor = mContentResolver.query(Uri.parse("content://rcs/thread"), null, bundle,
- null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(0);
- assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(null);
- assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
- 400);
- assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
- "New message");
- cursor.close();
- }
-
- @Test
- public void testQuery1To1Threads() {
- // verify two threads are returned in the query
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/p2p_thread"),
- new String[]{RCS_THREAD_ID_COLUMN}, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(2);
- }
-
- @Test
- public void testQueryGroupThreads() {
- // verify one thread is returned in the query
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/group_thread"),
- new String[]{GROUP_NAME_COLUMN}, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getString(0)).isEqualTo(GROUP_NAME);
- }
-
- @Test
- public void testQueryParticipant() {
- RcsParticipantQueryParams queryParameters = new RcsParticipantQueryParams.Builder()
- .build();
-
- Bundle bundle = new Bundle();
- bundle.putParcelable(PARTICIPANT_QUERY_PARAMETERS_KEY, queryParameters);
-
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/participant"), null, bundle,
- null);
- assertThat(cursor.getCount()).isEqualTo(2);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN))).isEqualTo(2);
- assertThat(cursor.getInt(cursor.getColumnIndex(CANONICAL_ADDRESS_ID_COLUMN))).isEqualTo(
- 100);
- assertThat(cursor.getString(cursor.getColumnIndex(RCS_ALIAS_COLUMN))).isEqualTo(
- "Some other alias");
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN))).isEqualTo(1);
- assertThat(cursor.getInt(cursor.getColumnIndex(CANONICAL_ADDRESS_ID_COLUMN))).isEqualTo(99);
- assertThat(cursor.getString(cursor.getColumnIndex(RCS_ALIAS_COLUMN))).isEqualTo(
- "Some alias");
- }
-
- @Test
- public void testQueryParticipantWithContinuation() {
- Uri participantUri = Uri.parse("content://rcs/participant");
-
- // Perform the initial query
- RcsParticipantQueryParams queryParameters =
- new RcsParticipantQueryParams.Builder().setAliasLike("%ali%").setSortProperty(
- RcsParticipantQueryParams.SORT_BY_ALIAS).setSortDirection(true)
- .setResultLimit(1).build();
-
- Bundle bundle = new Bundle();
- bundle.putParcelable(PARTICIPANT_QUERY_PARAMETERS_KEY, queryParameters);
-
- Cursor cursor = mContentResolver.query(participantUri, null, bundle, null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(0)).isEqualTo(1);
- assertThat(cursor.getInt(1)).isEqualTo(99);
- assertThat(cursor.getString(2)).isEqualTo("Some alias");
-
- // Perform the continuation query
- RcsQueryContinuationToken continuationToken = cursor.getExtras().getParcelable(
- QUERY_CONTINUATION_TOKEN);
- bundle.clear();
- bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
-
- cursor = mContentResolver.query(participantUri, null, bundle, null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(0)).isEqualTo(2);
- assertThat(cursor.getInt(1)).isEqualTo(100);
- assertThat(cursor.getString(2)).isEqualTo("Some other alias");
-
- // Perform the continuation query to verify no entries left
- continuationToken = cursor.getExtras().getParcelable(QUERY_CONTINUATION_TOKEN);
- bundle.clear();
- bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
-
- cursor = mContentResolver.query(participantUri, null, bundle, null);
- assertThat(cursor.getCount()).isEqualTo(0);
- continuationToken = cursor.getExtras().getParcelable(QUERY_CONTINUATION_TOKEN);
- assertThat(continuationToken).isNull();
- }
-
- @Test
- public void testQueryGroupParticipants() {
- // TODO - implement
- }
-
- @Test
- @Ignore // TODO: fix and un-ignore
- public void testQueryEvents() {
- RcsEventQueryParams queryParameters = new RcsEventQueryParams.Builder().build();
-
- Bundle bundle = new Bundle();
- bundle.putParcelable(EVENT_QUERY_PARAMETERS_KEY, queryParameters);
-
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/event"), null, bundle,
- null);
- assertThat(cursor.getCount()).isEqualTo(2);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(EVENT_TYPE_COLUMN))).isEqualTo(
- PARTICIPANT_JOINED_EVENT_TYPE);
- assertThat(cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN))).isEqualTo(
- 1);
- assertThat(cursor.getInt(cursor.getColumnIndex(DESTINATION_PARTICIPANT_ID_COLUMN))).isEqualTo(
- 2);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(EVENT_TYPE_COLUMN))).isEqualTo(
- GROUP_THREAD_NAME_CHANGED_EVENT);
- assertThat(cursor.getString(cursor.getColumnIndex(NEW_NAME_COLUMN))).isEqualTo(
- "New group name");
- }
-
- @Test
- @Ignore // TODO: fix and un-ignore
- public void testQueryEventsWithContinuation() {
- RcsEventQueryParams queryParameters =
- new RcsEventQueryParams.Builder().setResultLimit(1).setSortDirection(true)
- .build();
-
- Bundle bundle = new Bundle();
- bundle.putParcelable(EVENT_QUERY_PARAMETERS_KEY, queryParameters);
-
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/event"), null, bundle,
- null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(EVENT_TYPE_COLUMN))).isEqualTo(
- GROUP_THREAD_NAME_CHANGED_EVENT);
- assertThat(cursor.getString(cursor.getColumnIndex(NEW_NAME_COLUMN))).isEqualTo(
- "New group name");
- }
-
- @Test
- @Ignore // TODO: fix and un-ignore
- public void testQueryEventsWithTypeLimitation() {
- RcsEventQueryParams queryParameters =
- new RcsEventQueryParams.Builder().setEventType(
- GROUP_THREAD_NAME_CHANGED_EVENT).build();
- Bundle bundle = new Bundle();
- bundle.putParcelable(EVENT_QUERY_PARAMETERS_KEY, queryParameters);
-
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/event"), null, bundle,
- null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(EVENT_TYPE_COLUMN))).isEqualTo(
- GROUP_THREAD_NAME_CHANGED_EVENT);
- assertThat(cursor.getString(cursor.getColumnIndex(NEW_NAME_COLUMN))).isEqualTo(
- "New group name");
- }
-
- @Test
- @Ignore // TODO: fix and un-ignore
- public void testQueryMessages() {
- RcsMessageQueryParams queryParameters = new RcsMessageQueryParams.Builder().build();
- Bundle bundle = new Bundle();
- bundle.putParcelable(MESSAGE_QUERY_PARAMETERS_KEY, queryParameters);
-
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, bundle,
- null);
-
- assertThat(cursor.getCount()).isEqualTo(3);
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(3);
- assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(3);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(2);
- assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(1);
- assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(1);
- }
-
- @Test
- @Ignore // TODO: fix and un-ignore
- public void testQueryMessagesWithContinuation() {
- RcsMessageQueryParams queryParameters =
- new RcsMessageQueryParams.Builder().setMessageLike("%o%message").setResultLimit(
- 1).setSortProperty(RcsMessageQueryParams.SORT_BY_TIMESTAMP)
- .setSortDirection(true).build();
- Bundle bundle = new Bundle();
- bundle.putParcelable(MESSAGE_QUERY_PARAMETERS_KEY, queryParameters);
-
- // Perform the initial query
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, bundle,
- null);
-
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(3);
- assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(3);
- assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
- 200);
- assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TYPE_COLUMN))).isEqualTo(
- "Group message");
-
- // Perform the continuation query
- RcsQueryContinuationToken continuationToken = cursor.getExtras().getParcelable(
- QUERY_CONTINUATION_TOKEN);
- assertThat(continuationToken).isNotNull();
- bundle.clear();
- bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
-
- cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, bundle, null);
-
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(1);
- assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(1);
- assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
- 300);
- assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
- "Old message");
- }
-
- @Test
- @Ignore // TODO: fix and un-ignore
- public void testQueryMessagesWithThreadFilter() {
- RcsMessageQueryParams queryParameters =
- new RcsMessageQueryParams.Builder().setThread(new RcsGroupThread(null, 3))
- .build();
- Bundle bundle = new Bundle();
- bundle.putParcelable(MESSAGE_QUERY_PARAMETERS_KEY, queryParameters);
-
- // Perform the initial query
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, bundle,
- null);
-
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(3);
- assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(3);
- assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
- 200);
- assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
- "Group message");
-
- }
-
- @Test
- public void testQueryParticipantOf1To1Thread() {
- // query the participant back
- Uri queryUri = Uri.parse("content://rcs/p2p_thread/1/participant");
- Cursor cursor = mContentResolver.query(queryUri, null, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
-
- assertThat(cursor.getInt(1)).isEqualTo(99);
- assertThat(cursor.getString(2)).isEqualTo("Some alias");
- }
-
- @Test
- public void testQueryParticipantOfGroupThread() {
- // query all the participants in this thread
- Uri queryUri = Uri.parse("content://rcs/group_thread/3/participant");
- Cursor cursor = mContentResolver.query(queryUri, null, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
-
- assertThat(cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN))).isEqualTo(1);
- assertThat(cursor.getInt(cursor.getColumnIndex(CANONICAL_ADDRESS_ID_COLUMN))).isEqualTo(99);
- assertThat(cursor.getString(cursor.getColumnIndex(RCS_ALIAS_COLUMN))).isEqualTo(
- "Some alias");
- }
-
- @Test
- public void testQueryParticipantOfGroupThreadWithId() {
- Cursor cursor = mContentResolver.query(
- Uri.parse("content://rcs/group_thread/3/participant/1"), null, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
-
- assertThat(cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN))).isEqualTo(1);
- assertThat(cursor.getInt(cursor.getColumnIndex(CANONICAL_ADDRESS_ID_COLUMN))).isEqualTo(99);
- assertThat(cursor.getString(cursor.getColumnIndex(RCS_ALIAS_COLUMN))).isEqualTo(
- "Some alias");
- }
-
- @Test
- public void testQueryFileTransfer() {
- ContentValues values = new ContentValues();
- // add an incoming message to the thread 2
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/2/incoming_message"),
- values)).isEqualTo(Uri.parse("content://rcs/p2p_thread/2/incoming_message/4"));
-
- // add a file transfer
- values.put(SESSION_ID_COLUMN, "session_id");
- values.put(FILE_SIZE_COLUMN, 1234567890);
- assertThat(
- mContentResolver.insert(Uri.parse("content://rcs/message/4/file_transfer"),
- values)).isEqualTo(Uri.parse("content://rcs/file_transfer/1"));
-
- // query the file transfer back
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/file_transfer/1"), null,
- null, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(0)).isEqualTo(1);
- assertThat(cursor.getInt(1)).isEqualTo(4);
- assertThat(cursor.getString(2)).isEqualTo("session_id");
- assertThat(cursor.getLong(5)).isEqualTo(1234567890);
- }
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderTestable.java b/tests/src/com/android/providers/telephony/RcsProviderTestable.java
deleted file mode 100644
index 569fcdb..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderTestable.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-package com.android.providers.telephony;
-
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.telephony.TelephonyManager;
-import android.test.mock.MockContentResolver;
-import android.test.mock.MockContext;
-
-import org.mockito.Mockito;
-
-/**
- * A subclass of RcsProvider used for testing on an in-memory database
- */
-public class RcsProviderTestable extends RcsProvider {
- private MockContextWithProvider mockContextWithProvider;
-
- @Override
- public boolean onCreate() {
- mockContextWithProvider = new MockContextWithProvider(this);
- mDbOpenHelper = new InMemoryRcsDatabase();
- mParticipantHelper = new RcsProviderParticipantHelper(mDbOpenHelper);
- mThreadHelper = new RcsProviderThreadHelper(mDbOpenHelper);
- mMessageHelper = new RcsProviderMessageHelper(mDbOpenHelper);
- mEventHelper = new RcsProviderEventHelper(mDbOpenHelper);
- return true;
- }
-
- protected void tearDown() {
- mDbOpenHelper.close();
- }
-
- public SQLiteDatabase getWritableDatabase() {
- return mDbOpenHelper.getWritableDatabase();
- }
-
- class InMemoryRcsDatabase extends SQLiteOpenHelper {
- InMemoryRcsDatabase() {
- super(null, // no context is needed for in-memory db
- null, // db file name is null for in-memory db
- null, // CursorFactory is null by default
- 1); // db version is no-op for tests
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- MmsSmsDatabaseHelper mmsSmsDatabaseHelper = new MmsSmsDatabaseHelper(
- mockContextWithProvider, null);
- mmsSmsDatabaseHelper.createMmsTables(db);
- mmsSmsDatabaseHelper.createSmsTables(db);
- mmsSmsDatabaseHelper.createCommonTables(db);
-
- RcsProviderThreadHelper.createThreadTables(db);
- RcsProviderParticipantHelper.createParticipantTables(db);
- RcsProviderMessageHelper.createRcsMessageTables(db);
- RcsProviderEventHelper.createRcsEventTables(db);
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- // no-op
- }
- }
-
- static class MockContextWithProvider extends MockContext {
- private final MockContentResolver mResolver;
-
- MockContextWithProvider(RcsProvider rcsProvider) {
- mResolver = new MockContentResolver();
-
- // Add authority="rcs" to given smsProvider
- ProviderInfo providerInfo = new ProviderInfo();
- providerInfo.authority = RcsProvider.AUTHORITY;
- rcsProvider.attachInfoForTesting(this, providerInfo);
- mResolver.addProvider(RcsProvider.AUTHORITY, rcsProvider);
- }
-
- @Override
- public MockContentResolver getContentResolver() {
- return mResolver;
- }
-
- @Override
- public PackageManager getPackageManager() {
- return Mockito.mock(PackageManager.class);
- }
-
- @Override
- public Object getSystemService(String name) {
- switch (name) {
- case Context.APP_OPS_SERVICE:
- return Mockito.mock(AppOpsManager.class);
- case Context.TELEPHONY_SERVICE:
- return Mockito.mock(TelephonyManager.class);
- default:
- return null;
- }
- }
-
- @Override
- public boolean isCredentialProtectedStorage() {
- return false;
- }
- }
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderUpdateTest.java b/tests/src/com/android/providers/telephony/RcsProviderUpdateTest.java
deleted file mode 100644
index 4ba7c1c..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderUpdateTest.java
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright (C) 2018 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
- */
-package com.android.providers.telephony;
-
-import static android.provider.Telephony.RcsColumns.Rcs1To1ThreadColumns.FALLBACK_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.HEIGHT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.WIDTH_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.OWNER_PARTICIPANT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns.ARRIVAL_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.ORIGINATION_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageDeliveryColumns.DELIVERED_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_ALIAS_COLUMN;
-
-import static com.android.providers.telephony.RcsProviderHelper.setup1To1Thread;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.Telephony.RcsColumns.RcsMessageDeliveryColumns;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsProviderUpdateTest {
- private MockContentResolver mContentResolver;
- private RcsProviderTestable mRcsProvider;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mRcsProvider = new RcsProviderTestable();
- RcsProviderTestable.MockContextWithProvider
- context = new RcsProviderTestable.MockContextWithProvider(mRcsProvider);
- mContentResolver = context.getContentResolver();
-
- // insert a participant
- // first into the MmsSmsProvider
- mRcsProvider.getWritableDatabase().execSQL(
- "INSERT INTO canonical_addresses VALUES (1, \"+15551234567\")");
-
- // then into the RcsProvider
- ContentValues participantValues = new ContentValues();
- participantValues.put(RCS_ALIAS_COLUMN, "Bob");
- participantValues.put(CANONICAL_ADDRESS_ID_COLUMN, 1);
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/participant"),
- participantValues)).isEqualTo(Uri.parse("content://rcs/participant/1"));
-
- // insert fallback threads
- mRcsProvider.getWritableDatabase().execSQL("INSERT INTO threads(_id) VALUES (1)");
- mRcsProvider.getWritableDatabase().execSQL("INSERT INTO threads(_id) VALUES (2)");
-
- setup1To1Thread(mContentResolver);
-
- // insert one group thread
- ContentValues groupContentValues = new ContentValues();
- groupContentValues.put(OWNER_PARTICIPANT_COLUMN, 1);
- groupContentValues.put(GROUP_NAME_COLUMN, "Name");
- Uri groupThreadUri = Uri.parse("content://rcs/group_thread");
- assertThat(mContentResolver.insert(groupThreadUri, groupContentValues)).isEqualTo(
- Uri.parse("content://rcs/group_thread/2"));
-
- Uri groupInsertionUri = Uri.parse("content://rcs/group_thread/2/participant/1");
- assertThat(mContentResolver.insert(groupInsertionUri, null)).isEqualTo(groupInsertionUri);
-
- // add incoming and outgoing messages to both threads
- ContentValues messageValues = new ContentValues();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/incoming_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"));
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/p2p_thread/1/outgoing_message/2"));
- assertThat(
- mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/incoming_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/group_thread/2/incoming_message/3"));
- assertThat(
- mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/outgoing_message"),
- messageValues)).isEqualTo(
- Uri.parse("content://rcs/group_thread/2/outgoing_message/4"));
-
- // add message delivery to the outgoing messages
- ContentValues deliveryValues = new ContentValues();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/outgoing_message/2/delivery/1"),
- deliveryValues)).isEqualTo(
- Uri.parse("content://rcs/outgoing_message/2/delivery/1"));
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/outgoing_message/4/delivery/1"),
- deliveryValues)).isEqualTo(
- Uri.parse("content://rcs/outgoing_message/4/delivery/1"));
-
- // add a file transfer to an incoming message
- ContentValues fileTransferValues = new ContentValues();
- assertThat(mContentResolver.insert(Uri.parse("content://rcs/message/3/file_transfer"),
- fileTransferValues)).isEqualTo(Uri.parse("content://rcs/file_transfer/1"));
- }
-
- @After
- public void tearDown() {
- mRcsProvider.tearDown();
- }
-
- @Test
- public void testUpdate1To1ThreadWithSelection() {
- // update the fallback thread id
- ContentValues contentValues = new ContentValues(1);
- contentValues.put(FALLBACK_THREAD_ID_COLUMN, 2);
- Uri p2pThreadUri = Uri.parse("content://rcs/p2p_thread");
-
- assertThat(mContentResolver.update(p2pThreadUri, contentValues, "rcs_fallback_thread_id=1",
- null)).isEqualTo(1);
-
- // verify the thread is actually updated
- Cursor cursor = mContentResolver.query(p2pThreadUri,
- new String[]{FALLBACK_THREAD_ID_COLUMN}, "rcs_fallback_thread_id=2", null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(0)).isEqualTo(2);
- }
-
- @Test
- public void testUpdate1To1ThreadWithId() {
- // update the fallback thread id
- ContentValues contentValues = new ContentValues(1);
- contentValues.put(FALLBACK_THREAD_ID_COLUMN, 2);
- Uri p2pThreadUri = Uri.parse("content://rcs/p2p_thread/1");
- assertThat(mContentResolver.update(p2pThreadUri, contentValues, null, null)).isEqualTo(1);
-
- // verify the thread is actually updated
- Cursor cursor = mContentResolver.query(p2pThreadUri,
- new String[]{FALLBACK_THREAD_ID_COLUMN}, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getInt(0)).isEqualTo(2);
- }
-
- @Test
- public void testUpdateGroupThreadWithSelection() {
- // update the group name
- ContentValues contentValues = new ContentValues(1);
- contentValues.put(GROUP_NAME_COLUMN, "New name");
- Uri groupThreadUri = Uri.parse("content://rcs/group_thread");
- assertThat(mContentResolver.update(groupThreadUri, contentValues, "group_name=\"Name\"",
- null)).isEqualTo(1);
-
- // verify the thread is actually updated
- Cursor cursor = mContentResolver.query(groupThreadUri, new String[]{GROUP_NAME_COLUMN},
- "group_name=\"New name\"", null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
-
- cursor.moveToNext();
- assertThat(cursor.getString(0)).isEqualTo("New name");
- }
-
- @Test
- public void testUpdateGroupThreadWithId() {
- // update the group name
- ContentValues contentValues = new ContentValues(1);
- contentValues.put(GROUP_NAME_COLUMN, "New name");
- Uri groupThreadUri = Uri.parse("content://rcs/group_thread/2");
- assertThat(mContentResolver.update(groupThreadUri, contentValues, null, null)).isEqualTo(1);
-
- // verify the thread is actually updated
- Cursor cursor = mContentResolver.query(groupThreadUri, new String[]{GROUP_NAME_COLUMN},
- null, null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getString(0)).isEqualTo("New name");
- }
-
- @Test
- public void testUpdateParticipantWithId() {
- // change the participant name from Bob to Bobby
- ContentValues contentValues = new ContentValues(1);
- contentValues.put(RCS_ALIAS_COLUMN, "Bobby");
-
- Uri participantUri = Uri.parse("content://rcs/participant/1");
-
- assertThat(mContentResolver.update(participantUri, contentValues, null, null)).isEqualTo(1);
-
- // verify participant is actually updated
- Cursor cursor = mContentResolver.query(participantUri, new String[]{RCS_ALIAS_COLUMN}, null,
- null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getString(0)).isEqualTo("Bobby");
- }
-
- @Test
- public void testUpdate1To1ThreadParticipantFails() {
- assertThat(
- mContentResolver.update(Uri.parse("content://rcs/p2p_thread/1/participant/1"), null,
- null, null)).isEqualTo(0);
- }
-
- @Test
- public void testUpdateGroupParticipantFails() {
- assertThat(mContentResolver.update(Uri.parse("content://rcs/group_thread/2/participant/1"),
- null, null, null)).isEqualTo(0);
- }
-
- @Test
- public void testUpdateUnifiedMessageViewFails() {
- ContentValues updateValues = new ContentValues();
- updateValues.put(ORIGINATION_TIMESTAMP_COLUMN, 1234567890);
-
- assertThat(mContentResolver.update(Uri.parse("content://rcs/message"), updateValues, null,
- null)).isEqualTo(0);
- assertThat(mContentResolver.update(Uri.parse("content://rcs/message/1"), updateValues, null,
- null)).isEqualTo(0);
- }
-
- @Test
- public void testUpdateMessageOnThreadFails() {
- ContentValues updateValues = new ContentValues();
- updateValues.put(ORIGINATION_TIMESTAMP_COLUMN, 1234567890);
-
- assertThat(mContentResolver.update(Uri.parse("content://rcs/p2p_thread/1/incoming_message"),
- updateValues, null, null)).isEqualTo(0);
- assertThat(
- mContentResolver.update(Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"),
- updateValues, null, null)).isEqualTo(0);
- assertThat(
- mContentResolver.update(Uri.parse("content://rcs/group_thread/2/outgoing_message"),
- updateValues, null, null)).isEqualTo(0);
- assertThat(mContentResolver.update(
- Uri.parse("content://rcs/groupp_thread/2/outgoing_message/1"), updateValues, null,
- null)).isEqualTo(0);
- }
-
- @Test
- public void testUpdateMessage() {
- // update the message
- ContentValues updateValues = new ContentValues(1);
- updateValues.put(ORIGINATION_TIMESTAMP_COLUMN, 1234567890);
- assertThat(
- mContentResolver.update(Uri.parse("content://rcs/outgoing_message/2"), updateValues,
- null, null)).isEqualTo(1);
-
- // verify the value is actually updated
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/outgoing_message/2"), null,
- null, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getLong(5)).isEqualTo(1234567890);
- cursor.close();
- }
-
- @Test
- @Ignore // TODO: fix and un-ignore
- public void testUpdateIncomingMessageSpecificColumn() {
- // update the message
- ContentValues updateValues = new ContentValues(1);
- updateValues.put(ARRIVAL_TIMESTAMP_COLUMN, 987654321);
- assertThat(
- mContentResolver.update(Uri.parse("content://rcs/incoming_message/3"), updateValues,
- null, null)).isEqualTo(1);
-
- // verify the value is actually updated
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/incoming_message/3"), null,
- null, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getLong(7)).isEqualTo(987654321);
- cursor.close();
- }
-
- @Test
- public void testUpdateMessageDelivery() {
- ContentValues updateValues = new ContentValues();
- updateValues.put(DELIVERED_TIMESTAMP_COLUMN, 12345);
- updateValues.put(RcsMessageDeliveryColumns.SEEN_TIMESTAMP_COLUMN, 54321);
-
- assertThat(mContentResolver.update(Uri.parse("content://rcs/outgoing_message/2/delivery/1"),
- updateValues, null, null)).isEqualTo(1);
-
- // verify the value is actually updated
- Cursor cursor = mContentResolver.query(
- Uri.parse("content://rcs/outgoing_message/2/delivery"), null, null, null, null,
- null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getInt(0)).isEqualTo(2);
- assertThat(cursor.getInt(1)).isEqualTo(1);
- assertThat(cursor.getLong(2)).isEqualTo(12345);
- assertThat(cursor.getLong(3)).isEqualTo(54321);
- }
-
- @Test
- public void testUpdateFileTransfer() {
- ContentValues updateValues = new ContentValues();
- updateValues.put(WIDTH_COLUMN, 640);
- updateValues.put(HEIGHT_COLUMN, 480);
-
- assertThat(mContentResolver.update(Uri.parse("content://rcs/file_transfer/1"), updateValues,
- null, null)).isEqualTo(1);
-
- // verify that the values are actually updated
- Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/file_transfer/1"), null,
- null, null, null, null);
- assertThat(cursor.getCount()).isEqualTo(1);
- cursor.moveToNext();
- assertThat(cursor.getInt(8)).isEqualTo(640);
- assertThat(cursor.getInt(9)).isEqualTo(480);
- }
-}
diff --git a/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java b/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java
index b6f5508..0cd66e3 100644
--- a/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java
+++ b/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java
@@ -164,12 +164,12 @@
final int voiceRegState = ss.getVoiceRegState();
final int dataRegState = ss.getDataRegState();
- final String voiceOperatorAlphaLong = ss.getVoiceOperatorAlphaLong();
- final String voiceOperatorAlphaShort = ss.getVoiceOperatorAlphaShort();
- final String voiceOperatorNumeric = ss.getVoiceOperatorNumeric();
- final String dataOperatorAlphaLong = ss.getDataOperatorAlphaLong();
- final String dataOperatorAlphaShort = ss.getDataOperatorAlphaShort();
- final String dataOperatorNumeric = ss.getDataOperatorNumeric();
+ final String voiceOperatorAlphaLong = ss.getOperatorAlphaLong();
+ final String voiceOperatorAlphaShort = ss.getOperatorAlphaShort();
+ final String voiceOperatorNumeric = ss.getOperatorNumeric();
+ final String dataOperatorAlphaLong = ss.getOperatorAlphaLong();
+ final String dataOperatorAlphaShort = ss.getOperatorAlphaShort();
+ final String dataOperatorNumeric = ss.getOperatorNumeric();
final int isManualNetworkSelection = (ss.getIsManualSelection()) ? 1 : 0;
final int rilVoiceRadioTechnology = ss.getRilVoiceRadioTechnology();
final int rilDataRadioTechnology = ss.getRilDataRadioTechnology();
diff --git a/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java b/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java
index 8287352..26df3c0 100644
--- a/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java
@@ -59,7 +59,7 @@
public void setUp() {
Log.d(TAG, "setUp() +");
mContext = InstrumentationRegistry.getContext();
- mHelper = new TelephonyProvider.DatabaseHelper(mContext);
+ mHelper = new TelephonyProviderTestable().new DatabaseHelper(mContext);
mInMemoryDbHelper = new InMemoryTelephonyProviderV5DbHelper();
Log.d(TAG, "setUp() -");
}
@@ -69,7 +69,7 @@
Log.d(TAG, "databaseHelperOnUpgrade_hasApnSetIdField");
// (5 << 16 | 6) is the first upgrade trigger in onUpgrade
SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
- mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+ mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
// the upgraded db must have the APN_SET_ID field
Cursor cursor = db.query("carriers", null, null, null, null, null, null);
@@ -84,7 +84,7 @@
Log.d(TAG, "databaseHelperOnUpgrade_hasSubscriptionTypeField");
// (5 << 16 | 6) is the first upgrade trigger in onUpgrade
SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
- mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+ mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
// the upgraded db must have the Telephony.Carriers.CARRIER_ID field
Cursor cursor = db.query("carriers", null, null, null, null, null, null);
@@ -97,7 +97,7 @@
public void databaseHelperOnUpgrade_hasCountryIsoField() {
Log.d(TAG, "databaseHelperOnUpgrade_hasCountryIsoField");
SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
- mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+ mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
// the upgraded db must have the Telephony.Carriers.CARRIER_ID field
Cursor cursor = db.query("simInfo", null, null, null, null, null, null);
@@ -110,7 +110,7 @@
public void databaseHelperOnUpgrade_hasProfileClassField() {
Log.d(TAG, "databaseHelperOnUpgrade_hasProfileClassField");
SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
- mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+ mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
// the upgraded db must have the PROFILE_CLASS field
Cursor cursor = db.query("siminfo", null, null, null, null, null, null);
@@ -124,7 +124,7 @@
Log.d(TAG, "databaseHelperOnUpgrade_hasSkip464XlatField");
// (5 << 16 | 6) is the first upgrade trigger in onUpgrade
SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
- mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+ mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
// the upgraded db must have the Telephony.Carriers.CARRIER_ID field
Cursor cursor = db.query("carriers", null, null, null, null, null, null);
@@ -138,7 +138,7 @@
Log.d(TAG, "databaseHelperOnUpgrade_columnsMatchNewlyCreatedDb");
// (5 << 16 | 6) is the first upgrade trigger in onUpgrade
SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
- mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+ mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
// compare upgraded carriers table to a carriers table created from scratch
db.execSQL(TelephonyProvider.getStringForCarrierTableCreation("carriers_full"));
@@ -174,7 +174,7 @@
Log.d(TAG, "databaseHelperOnUpgrade_hasSubscriptionTypeField");
// (5 << 16 | 6) is the first upgrade trigger in onUpgrade
SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
- mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+ mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
// the upgraded db must have the SubscriptionManager.SUBSCRIPTION_TYPE field
Cursor cursor = db.query("siminfo", null, null, null, null, null, null);
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
index 47c1dc6..bf85625 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
@@ -39,6 +39,7 @@
import android.test.mock.MockContentResolver;
import android.test.mock.MockContext;
import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -93,6 +94,7 @@
private static final String TEST_MCC = "123";
private static final String TEST_MNC = "456";
private static final String TEST_SPN = TelephonyProviderTestable.TEST_SPN;
+ private static final int TEST_CARRIERID = 1;
// Used to test the path for URL_TELEPHONY_USING_SUBID with subid 1
private static final Uri CONTENT_URI_WITH_SUBID = Uri.parse(
@@ -155,6 +157,7 @@
doReturn(mIcRecords).when(mUiccController).getIccRecords(anyInt(), anyInt());
doReturn(TEST_SPN).when(mIcRecords).getServiceProviderName();
doReturn(TEST_SPN).when(mIcRecords).getServiceProviderNameWithBrandOverride();
+ doReturn(TEST_CARRIERID).when(mTelephonyManager).getSimCarrierId();
// Add authority="telephony" to given telephonyProvider
ProviderInfo providerInfo = new ProviderInfo();
@@ -183,6 +186,16 @@
}
@Override
+ public String getSystemServiceName(Class<?> serviceClass) {
+ if (serviceClass.equals(TelephonyManager.class)) {
+ return Context.TELEPHONY_SERVICE;
+ } else {
+ Log.d(TAG, "getSystemServiceName: returning null");
+ return null;
+ }
+ }
+
+ @Override
public Resources getResources() {
Log.d(TAG, "getResources: returning null");
return null;
@@ -1479,15 +1492,15 @@
@Test
@SmallTest
- public void testSIMAPNLIST_APNMatchTheMCCMNCAndMVNO() {
- // Test on getCurrentAPNList() step 1
+ public void testSIMAPNLIST_MatchTheMVNOAPN() {
+ // Test on getSubscriptionMatchingAPNList() step 1
final String apnName = "apnName";
final String carrierName = "name";
final String numeric = TEST_OPERATOR;
final String mvnoType = "spn";
final String mvnoData = TEST_SPN;
- // Insert the APN and DB only have the MCC/MNC and MVNO APN
+ // Insert the MVNO APN
ContentValues contentValues = new ContentValues();
contentValues.put(Carriers.APN, apnName);
contentValues.put(Carriers.NAME, carrierName);
@@ -1496,6 +1509,13 @@
contentValues.put(Carriers.MVNO_MATCH_DATA, mvnoData);
mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+ // Insert the MNO APN
+ contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.NUMERIC, numeric);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
// Query DB
final String[] testProjection =
{
@@ -1507,7 +1527,9 @@
Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
testProjection, null, null, null);
+ // When the DB has MVNO and MNO APN, the query based on SIM_APN_LIST will return MVNO APN
cursor.moveToFirst();
+ assertEquals(cursor.getCount(), 1);
assertEquals(apnName, cursor.getString(0));
assertEquals(carrierName, cursor.getString(1));
assertEquals(numeric, cursor.getString(2));
@@ -1516,13 +1538,13 @@
@Test
@SmallTest
- public void testSIMAPNLIST_APNMatchTheParentMCCMNC() {
- // Test on getCurrentAPNList() step 2
+ public void testSIMAPNLIST_MatchTheMNOAPN() {
+ // Test on getSubscriptionMatchingAPNList() step 2
final String apnName = "apnName";
final String carrierName = "name";
final String numeric = TEST_OPERATOR;
- // Insert the APN and DB only have the MNO APN
+ // Insert the MNO APN
ContentValues contentValues = new ContentValues();
contentValues.put(Carriers.APN, apnName);
contentValues.put(Carriers.NAME, carrierName);
@@ -1544,4 +1566,91 @@
assertEquals(carrierName, cursor.getString(1));
assertEquals(numeric, cursor.getString(2));
}
+
+ @Test
+ @SmallTest
+ public void testSIMAPNLIST_MatchTheCarrierIDANDMNOAPN() {
+ // Test on getSubscriptionMatchingAPNList() will return the {MCCMNC}
+ final String apnName = "apnName";
+ final String carrierName = "name";
+ final int carrierId = TEST_CARRIERID;
+
+ // Add the APN that only have carrier id
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.CARRIER_ID, carrierId);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+ // Add MNO APN that added by user
+ contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+ contentValues.put(Carriers.EDITED_STATUS, Carriers.UNEDITED);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+ // Query DB
+ final String[] testProjection =
+ {
+ Carriers.APN,
+ Carriers.NAME,
+ Carriers.CARRIER_ID,
+ };
+ Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST, testProjection, null, null, null);
+
+ // The query based on SIM_APN_LIST will return MNO APN and the APN that has carrier id
+ assertEquals(cursor.getCount(), 2);
+ }
+
+ @Test
+ @SmallTest
+ public void testSIMAPNLIST_MatchTheCarrierAPNAndMVNOAPN() {
+ final String apnName = "apnName";
+ final String carrierName = "name";
+ final String mvnoType = "spn";
+ final String mvnoData = TEST_SPN;
+ final int carrierId = TEST_CARRIERID;
+
+ // Add the APN that only have carrier id
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.CARRIER_ID, carrierId);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+ // Add MVNO APN that added by user
+ contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+ contentValues.put(Carriers.MVNO_TYPE, mvnoType);
+ contentValues.put(Carriers.MVNO_MATCH_DATA, mvnoData);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+ // Add MNO APN that added by user
+ contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+ // Query DB
+ final String[] testProjection =
+ {
+ Carriers.APN,
+ Carriers.NAME,
+ Carriers.CARRIER_ID,
+ Carriers.MVNO_TYPE,
+ };
+ Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
+ testProjection, null, null, null);
+
+ // The query based on SIM_APN_LIST will return MVNO APN and the APN that has carrier id
+ assertEquals(cursor.getCount(), 2);
+ while(cursor.moveToNext()) {
+ assertTrue(!TextUtils.isEmpty(cursor.getString(2))
+ || !TextUtils.isEmpty(cursor.getString(3)));
+ }
+ }
}