1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.internal.telephony.ims; 17 18 import static android.provider.Telephony.RcsColumns.RcsEventTypes.ICON_CHANGED_EVENT_TYPE; 19 import static android.provider.Telephony.RcsColumns.RcsEventTypes.NAME_CHANGED_EVENT_TYPE; 20 import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE; 21 import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_JOINED_EVENT_TYPE; 22 import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_LEFT_EVENT_TYPE; 23 import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.RCS_GROUP_THREAD_URI; 24 import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_URI; 25 import static android.provider.Telephony.RcsColumns.RcsParticipantEventColumns.ALIAS_CHANGE_EVENT_URI_PART; 26 import static android.provider.Telephony.RcsColumns.RcsParticipantEventColumns.NEW_ALIAS_COLUMN; 27 import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN; 28 import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.DESTINATION_PARTICIPANT_ID_COLUMN; 29 import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.EVENT_TYPE_COLUMN; 30 import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.ICON_CHANGED_URI_PART; 31 import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NAME_CHANGED_URI_PART; 32 import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_ICON_URI_COLUMN; 33 import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_NAME_COLUMN; 34 import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.PARTICIPANT_JOINED_URI_PART; 35 import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.PARTICIPANT_LEFT_URI_PART; 36 import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.SOURCE_PARTICIPANT_ID_COLUMN; 37 import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.TIMESTAMP_COLUMN; 38 import static android.provider.Telephony.RcsColumns.RcsUnifiedEventHelper.RCS_EVENT_QUERY_URI; 39 import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN; 40 41 import android.content.ContentResolver; 42 import android.content.ContentValues; 43 import android.database.Cursor; 44 import android.net.Uri; 45 import android.os.Bundle; 46 import android.os.RemoteException; 47 import android.telephony.Rlog; 48 import android.telephony.ims.RcsEventDescriptor; 49 import android.telephony.ims.RcsEventQueryResultDescriptor; 50 import android.telephony.ims.RcsGroupThreadIconChangedEventDescriptor; 51 import android.telephony.ims.RcsGroupThreadNameChangedEventDescriptor; 52 import android.telephony.ims.RcsGroupThreadParticipantJoinedEventDescriptor; 53 import android.telephony.ims.RcsGroupThreadParticipantLeftEventDescriptor; 54 import android.telephony.ims.RcsParticipantAliasChangedEventDescriptor; 55 import android.telephony.ims.RcsQueryContinuationToken; 56 57 import java.util.ArrayList; 58 import java.util.List; 59 60 class RcsEventQueryHelper { 61 private final ContentResolver mContentResolver; 62 RcsEventQueryHelper(ContentResolver contentResolver)63 RcsEventQueryHelper(ContentResolver contentResolver) { 64 mContentResolver = contentResolver; 65 } 66 getParticipantEventInsertionUri(int participantId)67 Uri getParticipantEventInsertionUri(int participantId) { 68 return RCS_PARTICIPANT_URI.buildUpon().appendPath(Integer.toString(participantId)) 69 .appendPath(ALIAS_CHANGE_EVENT_URI_PART).build(); 70 } 71 performEventQuery(Bundle bundle)72 RcsEventQueryResultDescriptor performEventQuery(Bundle bundle) throws RemoteException { 73 RcsQueryContinuationToken continuationToken = null; 74 List<RcsEventDescriptor> eventList = new ArrayList<>(); 75 76 try (Cursor cursor = mContentResolver.query(RCS_EVENT_QUERY_URI, null, bundle, null)) { 77 if (cursor == null) { 78 throw new RemoteException("Event query failed, bundle: " + bundle); 79 } 80 81 while (cursor.moveToNext()) { 82 int eventType = cursor.getInt(cursor.getColumnIndex(EVENT_TYPE_COLUMN)); 83 switch (eventType) { 84 case PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE: 85 eventList.add(createNewParticipantAliasChangedEvent(cursor)); 86 break; 87 case PARTICIPANT_JOINED_EVENT_TYPE: 88 eventList.add(createNewParticipantJoinedEvent(cursor)); 89 break; 90 case PARTICIPANT_LEFT_EVENT_TYPE: 91 eventList.add(createNewParticipantLeftEvent(cursor)); 92 break; 93 case NAME_CHANGED_EVENT_TYPE: 94 eventList.add(createNewGroupNameChangedEvent(cursor)); 95 break; 96 case ICON_CHANGED_EVENT_TYPE: 97 eventList.add(createNewGroupIconChangedEvent(cursor)); 98 break; 99 default: 100 Rlog.e(RcsMessageStoreController.TAG, 101 "RcsEventQueryHelper: invalid event type: " + eventType); 102 } 103 } 104 105 Bundle cursorExtras = cursor.getExtras(); 106 if (cursorExtras != null) { 107 continuationToken = cursorExtras.getParcelable(QUERY_CONTINUATION_TOKEN); 108 } 109 } 110 111 return new RcsEventQueryResultDescriptor(continuationToken, eventList); 112 } 113 createGroupThreadEvent(int eventType, long timestamp, int threadId, int originationParticipantId, ContentValues eventSpecificValues)114 int createGroupThreadEvent(int eventType, long timestamp, int threadId, 115 int originationParticipantId, ContentValues eventSpecificValues) 116 throws RemoteException { 117 ContentValues values = new ContentValues(eventSpecificValues); 118 values.put(EVENT_TYPE_COLUMN, eventType); 119 values.put(TIMESTAMP_COLUMN, timestamp); 120 values.put(SOURCE_PARTICIPANT_ID_COLUMN, originationParticipantId); 121 122 Uri eventUri = RCS_GROUP_THREAD_URI.buildUpon().appendPath( 123 Integer.toString(threadId)).appendPath(getPathForEventType(eventType)).build(); 124 Uri insertionUri = mContentResolver.insert(eventUri, values); 125 126 int eventId = 0; 127 if (insertionUri != null) { 128 eventId = Integer.parseInt(insertionUri.getLastPathSegment()); 129 } 130 131 if (eventId <= 0) { 132 throw new RemoteException( 133 "Could not create event with type: " + eventType + " on thread: " + threadId); 134 } 135 return eventId; 136 } 137 getPathForEventType(int eventType)138 private String getPathForEventType(int eventType) throws RemoteException { 139 switch (eventType) { 140 case PARTICIPANT_JOINED_EVENT_TYPE: 141 return PARTICIPANT_JOINED_URI_PART; 142 case PARTICIPANT_LEFT_EVENT_TYPE: 143 return PARTICIPANT_LEFT_URI_PART; 144 case NAME_CHANGED_EVENT_TYPE: 145 return NAME_CHANGED_URI_PART; 146 case ICON_CHANGED_EVENT_TYPE: 147 return ICON_CHANGED_URI_PART; 148 default: 149 throw new RemoteException("Event type unrecognized: " + eventType); 150 } 151 } 152 createNewGroupIconChangedEvent(Cursor cursor)153 private RcsGroupThreadIconChangedEventDescriptor createNewGroupIconChangedEvent(Cursor cursor) { 154 String newIcon = cursor.getString(cursor.getColumnIndex(NEW_ICON_URI_COLUMN)); 155 156 return new RcsGroupThreadIconChangedEventDescriptor( 157 cursor.getLong(cursor.getColumnIndex(TIMESTAMP_COLUMN)), 158 cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN)), 159 cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN)), 160 newIcon == null ? null : Uri.parse(newIcon)); 161 } 162 createNewGroupNameChangedEvent(Cursor cursor)163 private RcsGroupThreadNameChangedEventDescriptor createNewGroupNameChangedEvent(Cursor cursor) { 164 return new RcsGroupThreadNameChangedEventDescriptor( 165 cursor.getLong(cursor.getColumnIndex(TIMESTAMP_COLUMN)), 166 cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN)), 167 cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN)), 168 cursor.getString(cursor.getColumnIndex(NEW_NAME_COLUMN))); 169 } 170 171 private RcsGroupThreadParticipantLeftEventDescriptor createNewParticipantLeftEvent(Cursor cursor)172 createNewParticipantLeftEvent(Cursor cursor) { 173 return new RcsGroupThreadParticipantLeftEventDescriptor( 174 cursor.getLong(cursor.getColumnIndex(TIMESTAMP_COLUMN)), 175 cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN)), 176 cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN)), 177 cursor.getInt(cursor.getColumnIndex(DESTINATION_PARTICIPANT_ID_COLUMN))); 178 } 179 180 private RcsGroupThreadParticipantJoinedEventDescriptor createNewParticipantJoinedEvent(Cursor cursor)181 createNewParticipantJoinedEvent(Cursor cursor) { 182 return new RcsGroupThreadParticipantJoinedEventDescriptor( 183 cursor.getLong(cursor.getColumnIndex(TIMESTAMP_COLUMN)), 184 cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN)), 185 cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN)), 186 cursor.getInt(cursor.getColumnIndex(DESTINATION_PARTICIPANT_ID_COLUMN))); 187 } 188 189 private RcsParticipantAliasChangedEventDescriptor createNewParticipantAliasChangedEvent(Cursor cursor)190 createNewParticipantAliasChangedEvent(Cursor cursor) { 191 return new RcsParticipantAliasChangedEventDescriptor( 192 cursor.getLong(cursor.getColumnIndex(TIMESTAMP_COLUMN)), 193 cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN)), 194 cursor.getString(cursor.getColumnIndex(NEW_ALIAS_COLUMN))); 195 } 196 } 197