• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.telephony.ims;
17 
18 import android.annotation.IntDef;
19 import android.annotation.NonNull;
20 import android.annotation.WorkerThread;
21 
22 import java.lang.annotation.Retention;
23 import java.lang.annotation.RetentionPolicy;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.Set;
27 
28 /**
29  * This is a single instance of a message sent or received over RCS.
30  *
31  * @hide
32  */
33 public abstract class RcsMessage {
34     /**
35      * The value to indicate that this {@link RcsMessage} does not have any location information.
36      */
37     public static final double LOCATION_NOT_SET = Double.MIN_VALUE;
38 
39     /**
40      * The status to indicate that this {@link RcsMessage}s status is not set yet.
41      */
42     public static final int NOT_SET = 0;
43 
44     /**
45      * The status to indicate that this {@link RcsMessage} is a draft and is not in the process of
46      * sending yet.
47      */
48     public static final int DRAFT = 1;
49 
50     /**
51      * The status to indicate that this {@link RcsMessage} was successfully sent.
52      */
53     public static final int QUEUED = 2;
54 
55     /**
56      * The status to indicate that this {@link RcsMessage} is actively being sent.
57      */
58     public static final int SENDING = 3;
59 
60     /**
61      * The status to indicate that this {@link RcsMessage} was successfully sent.
62      */
63     public static final int SENT = 4;
64 
65     /**
66      * The status to indicate that this {@link RcsMessage} failed to send in an attempt before, and
67      * now being retried.
68      */
69     public static final int RETRYING = 5;
70 
71     /**
72      * The status to indicate that this {@link RcsMessage} has permanently failed to send.
73      */
74     public static final int FAILED = 6;
75 
76     /**
77      * The status to indicate that this {@link RcsMessage} was successfully received.
78      */
79     public static final int RECEIVED = 7;
80 
81     /**
82      * The status to indicate that this {@link RcsMessage} was seen.
83      */
84     public static final int SEEN = 9;
85 
86     /**
87      * @hide
88      */
89     protected final RcsControllerCall mRcsControllerCall;
90 
91     /**
92      * @hide
93      */
94     protected final int mId;
95 
96     @IntDef({
97             DRAFT, QUEUED, SENDING, SENT, RETRYING, FAILED, RECEIVED, SEEN
98     })
99     @Retention(RetentionPolicy.SOURCE)
100     public @interface RcsMessageStatus {
101     }
102 
RcsMessage(RcsControllerCall rcsControllerCall, int id)103     RcsMessage(RcsControllerCall rcsControllerCall, int id) {
104         mRcsControllerCall = rcsControllerCall;
105         mId = id;
106     }
107 
108     /**
109      * Returns the row Id from the common message.
110      *
111      * @hide
112      */
getId()113     public int getId() {
114         return mId;
115     }
116 
117     /**
118      * @return Returns the subscription ID that this {@link RcsMessage} was sent from, or delivered
119      * to.
120      * @throws RcsMessageStoreException if the value could not be read from the storage
121      * @see android.telephony.SubscriptionInfo#getSubscriptionId
122      */
getSubscriptionId()123     public int getSubscriptionId() throws RcsMessageStoreException {
124         return mRcsControllerCall.call(
125                 (iRcs, callingPackage) -> iRcs.getMessageSubId(mId, isIncoming(), callingPackage));
126     }
127 
128     /**
129      * Sets the subscription ID that this {@link RcsMessage} was sent from, or delivered to and
130      * persists it into storage.
131      *
132      * @param subId The subscription ID to persists into storage.
133      * @throws RcsMessageStoreException if the value could not be persisted into storage
134      * @see android.telephony.SubscriptionInfo#getSubscriptionId
135      */
136     @WorkerThread
setSubscriptionId(int subId)137     public void setSubscriptionId(int subId) throws RcsMessageStoreException {
138         mRcsControllerCall.callWithNoReturn(
139                 (iRcs, callingPackage) -> iRcs.setMessageSubId(mId, isIncoming(), subId,
140                         callingPackage));
141     }
142 
143     /**
144      * Sets the status of this message and persists it into storage. Please see
145      * {@link RcsFileTransferPart#setFileTransferStatus(int)} to set statuses around file transfers.
146      *
147      * @throws RcsMessageStoreException if the value could not be persisted into storage
148      */
149     @WorkerThread
setStatus(@csMessageStatus int rcsMessageStatus)150     public void setStatus(@RcsMessageStatus int rcsMessageStatus) throws RcsMessageStoreException {
151         mRcsControllerCall.callWithNoReturn(
152                 (iRcs, callingPackage) -> iRcs.setMessageStatus(mId, isIncoming(), rcsMessageStatus,
153                         callingPackage));
154     }
155 
156     /**
157      * @return Returns the status of this message. Please see
158      * {@link RcsFileTransferPart#setFileTransferStatus(int)} to set statuses around file transfers.
159      * @throws RcsMessageStoreException if the value could not be read from the storage
160      */
161     @WorkerThread
getStatus()162     public @RcsMessageStatus int getStatus() throws RcsMessageStoreException {
163         return mRcsControllerCall.call(
164                 (iRcs, callingPackage) -> iRcs.getMessageStatus(mId, isIncoming(), callingPackage));
165     }
166 
167     /**
168      * Sets the origination timestamp of this message and persists it into storage. Origination is
169      * defined as when the sender tapped the send button.
170      *
171      * @param timestamp The origination timestamp value in milliseconds passed after midnight,
172      *                  January 1, 1970 UTC
173      * @throws RcsMessageStoreException if the value could not be persisted into storage
174      */
175     @WorkerThread
setOriginationTimestamp(long timestamp)176     public void setOriginationTimestamp(long timestamp) throws RcsMessageStoreException {
177         mRcsControllerCall.callWithNoReturn(
178                 (iRcs, callingPackage) -> iRcs.setMessageOriginationTimestamp(mId, isIncoming(),
179                         timestamp, callingPackage));
180     }
181 
182     /**
183      * @return Returns the origination timestamp of this message in milliseconds passed after
184      * midnight, January 1, 1970 UTC. Origination is defined as when the sender tapped the send
185      * button.
186      * @throws RcsMessageStoreException if the value could not be read from the storage
187      */
188     @WorkerThread
getOriginationTimestamp()189     public long getOriginationTimestamp() throws RcsMessageStoreException {
190         return mRcsControllerCall.call(
191                 (iRcs, callingPackage) -> iRcs.getMessageOriginationTimestamp(mId, isIncoming(),
192                         callingPackage));
193     }
194 
195     /**
196      * Sets the globally unique RCS message identifier for this message and persists it into
197      * storage. This function does not confirm that this message id is unique. Please see 4.4.5.2
198      * - GSMA RCC.53 (RCS Device API 1.6 Specification
199      *
200      * @param rcsMessageGlobalId The globally RCS message identifier
201      * @throws RcsMessageStoreException if the value could not be persisted into storage
202      */
203     @WorkerThread
setRcsMessageId(String rcsMessageGlobalId)204     public void setRcsMessageId(String rcsMessageGlobalId) throws RcsMessageStoreException {
205         mRcsControllerCall.callWithNoReturn(
206                 (iRcs, callingPackage) -> iRcs.setGlobalMessageIdForMessage(mId, isIncoming(),
207                         rcsMessageGlobalId, callingPackage));
208     }
209 
210     /**
211      * @return Returns the globally unique RCS message identifier for this message. Please see
212      * 4.4.5.2 - GSMA RCC.53 (RCS Device API 1.6 Specification
213      * @throws RcsMessageStoreException if the value could not be read from the storage
214      */
215     @WorkerThread
getRcsMessageId()216     public String getRcsMessageId() throws RcsMessageStoreException {
217         return mRcsControllerCall.call(
218                 (iRcs, callingPackage) -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming(),
219                         callingPackage));
220     }
221 
222     /**
223      * @return Returns the user visible text included in this message.
224      * @throws RcsMessageStoreException if the value could not be read from the storage
225      */
226     @WorkerThread
getText()227     public String getText() throws RcsMessageStoreException {
228         return mRcsControllerCall.call(
229                 (iRcs, callingPackage) -> iRcs.getTextForMessage(mId, isIncoming(),
230                         callingPackage));
231     }
232 
233     /**
234      * Sets the user visible text for this message and persists in storage.
235      *
236      * @param text The text this message now has
237      * @throws RcsMessageStoreException if the value could not be persisted into storage
238      */
239     @WorkerThread
setText(String text)240     public void setText(String text) throws RcsMessageStoreException {
241         mRcsControllerCall.callWithNoReturn(
242                 (iRcs, callingPackage) -> iRcs.setTextForMessage(mId, isIncoming(), text,
243                         callingPackage));
244     }
245 
246     /**
247      * @return Returns the associated latitude for this message, or
248      * {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location.
249      * @throws RcsMessageStoreException if the value could not be read from the storage
250      */
251     @WorkerThread
getLatitude()252     public double getLatitude() throws RcsMessageStoreException {
253         return mRcsControllerCall.call(
254                 (iRcs, callingPackage) -> iRcs.getLatitudeForMessage(mId, isIncoming(),
255                         callingPackage));
256     }
257 
258     /**
259      * Sets the latitude for this message and persists in storage.
260      *
261      * @param latitude The latitude for this location message.
262      * @throws RcsMessageStoreException if the value could not be persisted into storage
263      */
264     @WorkerThread
setLatitude(double latitude)265     public void setLatitude(double latitude) throws RcsMessageStoreException {
266         mRcsControllerCall.callWithNoReturn(
267                 (iRcs, callingPackage) -> iRcs.setLatitudeForMessage(mId, isIncoming(), latitude,
268                         callingPackage));
269     }
270 
271     /**
272      * @return Returns the associated longitude for this message, or
273      * {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location.
274      * @throws RcsMessageStoreException if the value could not be read from the storage
275      */
276     @WorkerThread
getLongitude()277     public double getLongitude() throws RcsMessageStoreException {
278         return mRcsControllerCall.call(
279                 (iRcs, callingPackage) -> iRcs.getLongitudeForMessage(mId, isIncoming(),
280                         callingPackage));
281     }
282 
283     /**
284      * Sets the longitude for this message and persists in storage.
285      *
286      * @param longitude The longitude for this location message.
287      * @throws RcsMessageStoreException if the value could not be persisted into storage
288      */
289     @WorkerThread
setLongitude(double longitude)290     public void setLongitude(double longitude) throws RcsMessageStoreException {
291         mRcsControllerCall.callWithNoReturn(
292                 (iRcs, callingPackage) -> iRcs.setLongitudeForMessage(mId, isIncoming(), longitude,
293                         callingPackage));
294     }
295 
296     /**
297      * Attaches an {@link RcsFileTransferPart} to this message and persists into storage.
298      *
299      * @param fileTransferCreationParameters The parameters to be used to create the
300      *                                       {@link RcsFileTransferPart}
301      * @return A new instance of {@link RcsFileTransferPart}
302      * @throws RcsMessageStoreException if the file transfer could not be persisted into storage.
303      */
304     @NonNull
305     @WorkerThread
insertFileTransfer( RcsFileTransferCreationParams fileTransferCreationParameters)306     public RcsFileTransferPart insertFileTransfer(
307             RcsFileTransferCreationParams fileTransferCreationParameters)
308             throws RcsMessageStoreException {
309         return new RcsFileTransferPart(mRcsControllerCall, mRcsControllerCall.call(
310                 (iRcs, callingPackage) -> iRcs.storeFileTransfer(mId, isIncoming(),
311                         fileTransferCreationParameters, callingPackage)));
312     }
313 
314     /**
315      * @return Returns all the {@link RcsFileTransferPart}s associated with this message in an
316      * unmodifiable set.
317      * @throws RcsMessageStoreException if the file transfers could not be read from the storage
318      */
319     @NonNull
320     @WorkerThread
getFileTransferParts()321     public Set<RcsFileTransferPart> getFileTransferParts() throws RcsMessageStoreException {
322         Set<RcsFileTransferPart> fileTransferParts = new HashSet<>();
323 
324         int[] fileTransferIds = mRcsControllerCall.call(
325                 (iRcs, callingPackage) -> iRcs.getFileTransfersAttachedToMessage(mId, isIncoming(),
326                         callingPackage));
327 
328         for (int fileTransfer : fileTransferIds) {
329             fileTransferParts.add(new RcsFileTransferPart(mRcsControllerCall, fileTransfer));
330         }
331 
332         return Collections.unmodifiableSet(fileTransferParts);
333     }
334 
335     /**
336      * Removes a {@link RcsFileTransferPart} from this message, and deletes it in storage.
337      *
338      * @param fileTransferPart The part to delete.
339      * @throws RcsMessageStoreException if the file transfer could not be removed from storage
340      */
341     @WorkerThread
removeFileTransferPart(@onNull RcsFileTransferPart fileTransferPart)342     public void removeFileTransferPart(@NonNull RcsFileTransferPart fileTransferPart)
343             throws RcsMessageStoreException {
344         if (fileTransferPart == null) {
345             return;
346         }
347 
348         mRcsControllerCall.callWithNoReturn(
349                 (iRcs, callingPackage) -> iRcs.deleteFileTransfer(fileTransferPart.getId(),
350                         callingPackage));
351     }
352 
353     /**
354      * @return Returns {@code true} if this message was received on this device, {@code false} if it
355      * was sent.
356      */
isIncoming()357     public abstract boolean isIncoming();
358 }
359