blob: 4601bfd0ff2c38b91eec60df3f572b4c5c0960dc [file] [log] [blame]
/*
* 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();
}