| /* |
| * 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 android.telephony.ims; |
| |
| import android.annotation.IntDef; |
| import android.annotation.NonNull; |
| import android.annotation.WorkerThread; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| /** |
| * This is a single instance of a message sent or received over RCS. |
| * |
| * @hide |
| */ |
| public abstract class RcsMessage { |
| /** |
| * The value to indicate that this {@link RcsMessage} does not have any location information. |
| */ |
| public static final double LOCATION_NOT_SET = Double.MIN_VALUE; |
| |
| /** |
| * The status to indicate that this {@link RcsMessage}s status is not set yet. |
| */ |
| public static final int NOT_SET = 0; |
| |
| /** |
| * The status to indicate that this {@link RcsMessage} is a draft and is not in the process of |
| * sending yet. |
| */ |
| public static final int DRAFT = 1; |
| |
| /** |
| * The status to indicate that this {@link RcsMessage} was successfully sent. |
| */ |
| public static final int QUEUED = 2; |
| |
| /** |
| * The status to indicate that this {@link RcsMessage} is actively being sent. |
| */ |
| public static final int SENDING = 3; |
| |
| /** |
| * The status to indicate that this {@link RcsMessage} was successfully sent. |
| */ |
| public static final int SENT = 4; |
| |
| /** |
| * The status to indicate that this {@link RcsMessage} failed to send in an attempt before, and |
| * now being retried. |
| */ |
| public static final int RETRYING = 5; |
| |
| /** |
| * The status to indicate that this {@link RcsMessage} has permanently failed to send. |
| */ |
| public static final int FAILED = 6; |
| |
| /** |
| * The status to indicate that this {@link RcsMessage} was successfully received. |
| */ |
| public static final int RECEIVED = 7; |
| |
| /** |
| * The status to indicate that this {@link RcsMessage} was seen. |
| */ |
| public static final int SEEN = 9; |
| |
| /** |
| * @hide |
| */ |
| protected final RcsControllerCall mRcsControllerCall; |
| |
| /** |
| * @hide |
| */ |
| protected final int mId; |
| |
| @IntDef({ |
| DRAFT, QUEUED, SENDING, SENT, RETRYING, FAILED, RECEIVED, SEEN |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface RcsMessageStatus { |
| } |
| |
| RcsMessage(RcsControllerCall rcsControllerCall, int id) { |
| mRcsControllerCall = rcsControllerCall; |
| mId = id; |
| } |
| |
| /** |
| * Returns the row Id from the common message. |
| * |
| * @hide |
| */ |
| public int getId() { |
| return mId; |
| } |
| |
| /** |
| * @return Returns the subscription ID that this {@link RcsMessage} was sent from, or delivered |
| * to. |
| * @throws RcsMessageStoreException if the value could not be read from the storage |
| * @see android.telephony.SubscriptionInfo#getSubscriptionId |
| */ |
| public int getSubscriptionId() throws RcsMessageStoreException { |
| return mRcsControllerCall.call( |
| (iRcs, callingPackage) -> iRcs.getMessageSubId(mId, isIncoming(), callingPackage)); |
| } |
| |
| /** |
| * Sets the subscription ID that this {@link RcsMessage} was sent from, or delivered to and |
| * persists it into storage. |
| * |
| * @param subId The subscription ID to persists into storage. |
| * @throws RcsMessageStoreException if the value could not be persisted into storage |
| * @see android.telephony.SubscriptionInfo#getSubscriptionId |
| */ |
| @WorkerThread |
| public void setSubscriptionId(int subId) throws RcsMessageStoreException { |
| mRcsControllerCall.callWithNoReturn( |
| (iRcs, callingPackage) -> iRcs.setMessageSubId(mId, isIncoming(), subId, |
| callingPackage)); |
| } |
| |
| /** |
| * Sets the status of this message and persists it into storage. Please see |
| * {@link RcsFileTransferPart#setFileTransferStatus(int)} to set statuses around file transfers. |
| * |
| * @throws RcsMessageStoreException if the value could not be persisted into storage |
| */ |
| @WorkerThread |
| public void setStatus(@RcsMessageStatus int rcsMessageStatus) throws RcsMessageStoreException { |
| mRcsControllerCall.callWithNoReturn( |
| (iRcs, callingPackage) -> iRcs.setMessageStatus(mId, isIncoming(), rcsMessageStatus, |
| callingPackage)); |
| } |
| |
| /** |
| * @return Returns the status of this message. Please see |
| * {@link RcsFileTransferPart#setFileTransferStatus(int)} to set statuses around file transfers. |
| * @throws RcsMessageStoreException if the value could not be read from the storage |
| */ |
| @WorkerThread |
| public @RcsMessageStatus int getStatus() throws RcsMessageStoreException { |
| return mRcsControllerCall.call( |
| (iRcs, callingPackage) -> iRcs.getMessageStatus(mId, isIncoming(), callingPackage)); |
| } |
| |
| /** |
| * Sets the origination timestamp of this message and persists it into storage. Origination is |
| * defined as when the sender tapped the send button. |
| * |
| * @param timestamp The origination timestamp value in milliseconds passed after midnight, |
| * January 1, 1970 UTC |
| * @throws RcsMessageStoreException if the value could not be persisted into storage |
| */ |
| @WorkerThread |
| public void setOriginationTimestamp(long timestamp) throws RcsMessageStoreException { |
| mRcsControllerCall.callWithNoReturn( |
| (iRcs, callingPackage) -> iRcs.setMessageOriginationTimestamp(mId, isIncoming(), |
| timestamp, callingPackage)); |
| } |
| |
| /** |
| * @return Returns the origination timestamp of this message in milliseconds passed after |
| * midnight, January 1, 1970 UTC. Origination is defined as when the sender tapped the send |
| * button. |
| * @throws RcsMessageStoreException if the value could not be read from the storage |
| */ |
| @WorkerThread |
| public long getOriginationTimestamp() throws RcsMessageStoreException { |
| return mRcsControllerCall.call( |
| (iRcs, callingPackage) -> iRcs.getMessageOriginationTimestamp(mId, isIncoming(), |
| callingPackage)); |
| } |
| |
| /** |
| * Sets the globally unique RCS message identifier for this message and persists it into |
| * storage. This function does not confirm that this message id is unique. Please see 4.4.5.2 |
| * - GSMA RCC.53 (RCS Device API 1.6 Specification |
| * |
| * @param rcsMessageGlobalId The globally RCS message identifier |
| * @throws RcsMessageStoreException if the value could not be persisted into storage |
| */ |
| @WorkerThread |
| public void setRcsMessageId(String rcsMessageGlobalId) throws RcsMessageStoreException { |
| mRcsControllerCall.callWithNoReturn( |
| (iRcs, callingPackage) -> iRcs.setGlobalMessageIdForMessage(mId, isIncoming(), |
| rcsMessageGlobalId, callingPackage)); |
| } |
| |
| /** |
| * @return Returns the globally unique RCS message identifier for this message. Please see |
| * 4.4.5.2 - GSMA RCC.53 (RCS Device API 1.6 Specification |
| * @throws RcsMessageStoreException if the value could not be read from the storage |
| */ |
| @WorkerThread |
| public String getRcsMessageId() throws RcsMessageStoreException { |
| return mRcsControllerCall.call( |
| (iRcs, callingPackage) -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming(), |
| callingPackage)); |
| } |
| |
| /** |
| * @return Returns the user visible text included in this message. |
| * @throws RcsMessageStoreException if the value could not be read from the storage |
| */ |
| @WorkerThread |
| public String getText() throws RcsMessageStoreException { |
| return mRcsControllerCall.call( |
| (iRcs, callingPackage) -> iRcs.getTextForMessage(mId, isIncoming(), |
| callingPackage)); |
| } |
| |
| /** |
| * Sets the user visible text for this message and persists in storage. |
| * |
| * @param text The text this message now has |
| * @throws RcsMessageStoreException if the value could not be persisted into storage |
| */ |
| @WorkerThread |
| public void setText(String text) throws RcsMessageStoreException { |
| mRcsControllerCall.callWithNoReturn( |
| (iRcs, callingPackage) -> iRcs.setTextForMessage(mId, isIncoming(), text, |
| callingPackage)); |
| } |
| |
| /** |
| * @return Returns the associated latitude for this message, or |
| * {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location. |
| * @throws RcsMessageStoreException if the value could not be read from the storage |
| */ |
| @WorkerThread |
| public double getLatitude() throws RcsMessageStoreException { |
| return mRcsControllerCall.call( |
| (iRcs, callingPackage) -> iRcs.getLatitudeForMessage(mId, isIncoming(), |
| callingPackage)); |
| } |
| |
| /** |
| * Sets the latitude for this message and persists in storage. |
| * |
| * @param latitude The latitude for this location message. |
| * @throws RcsMessageStoreException if the value could not be persisted into storage |
| */ |
| @WorkerThread |
| public void setLatitude(double latitude) throws RcsMessageStoreException { |
| mRcsControllerCall.callWithNoReturn( |
| (iRcs, callingPackage) -> iRcs.setLatitudeForMessage(mId, isIncoming(), latitude, |
| callingPackage)); |
| } |
| |
| /** |
| * @return Returns the associated longitude for this message, or |
| * {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location. |
| * @throws RcsMessageStoreException if the value could not be read from the storage |
| */ |
| @WorkerThread |
| public double getLongitude() throws RcsMessageStoreException { |
| return mRcsControllerCall.call( |
| (iRcs, callingPackage) -> iRcs.getLongitudeForMessage(mId, isIncoming(), |
| callingPackage)); |
| } |
| |
| /** |
| * Sets the longitude for this message and persists in storage. |
| * |
| * @param longitude The longitude for this location message. |
| * @throws RcsMessageStoreException if the value could not be persisted into storage |
| */ |
| @WorkerThread |
| public void setLongitude(double longitude) throws RcsMessageStoreException { |
| mRcsControllerCall.callWithNoReturn( |
| (iRcs, callingPackage) -> iRcs.setLongitudeForMessage(mId, isIncoming(), longitude, |
| callingPackage)); |
| } |
| |
| /** |
| * Attaches an {@link RcsFileTransferPart} to this message and persists into storage. |
| * |
| * @param fileTransferCreationParameters The parameters to be used to create the |
| * {@link RcsFileTransferPart} |
| * @return A new instance of {@link RcsFileTransferPart} |
| * @throws RcsMessageStoreException if the file transfer could not be persisted into storage. |
| */ |
| @NonNull |
| @WorkerThread |
| public RcsFileTransferPart insertFileTransfer( |
| RcsFileTransferCreationParams fileTransferCreationParameters) |
| throws RcsMessageStoreException { |
| return new RcsFileTransferPart(mRcsControllerCall, mRcsControllerCall.call( |
| (iRcs, callingPackage) -> iRcs.storeFileTransfer(mId, isIncoming(), |
| fileTransferCreationParameters, callingPackage))); |
| } |
| |
| /** |
| * @return Returns all the {@link RcsFileTransferPart}s associated with this message in an |
| * unmodifiable set. |
| * @throws RcsMessageStoreException if the file transfers could not be read from the storage |
| */ |
| @NonNull |
| @WorkerThread |
| public Set<RcsFileTransferPart> getFileTransferParts() throws RcsMessageStoreException { |
| Set<RcsFileTransferPart> fileTransferParts = new HashSet<>(); |
| |
| int[] fileTransferIds = mRcsControllerCall.call( |
| (iRcs, callingPackage) -> iRcs.getFileTransfersAttachedToMessage(mId, isIncoming(), |
| callingPackage)); |
| |
| for (int fileTransfer : fileTransferIds) { |
| fileTransferParts.add(new RcsFileTransferPart(mRcsControllerCall, fileTransfer)); |
| } |
| |
| return Collections.unmodifiableSet(fileTransferParts); |
| } |
| |
| /** |
| * Removes a {@link RcsFileTransferPart} from this message, and deletes it in storage. |
| * |
| * @param fileTransferPart The part to delete. |
| * @throws RcsMessageStoreException if the file transfer could not be removed from storage |
| */ |
| @WorkerThread |
| public void removeFileTransferPart(@NonNull RcsFileTransferPart fileTransferPart) |
| throws RcsMessageStoreException { |
| if (fileTransferPart == null) { |
| return; |
| } |
| |
| mRcsControllerCall.callWithNoReturn( |
| (iRcs, callingPackage) -> iRcs.deleteFileTransfer(fileTransferPart.getId(), |
| callingPackage)); |
| } |
| |
| /** |
| * @return Returns {@code true} if this message was received on this device, {@code false} if it |
| * was sent. |
| */ |
| public abstract boolean isIncoming(); |
| } |