summaryrefslogtreecommitdiffstats
path: root/src/com/android/messaging/datamodel/data/PendingAttachmentData.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/messaging/datamodel/data/PendingAttachmentData.java')
-rw-r--r--src/com/android/messaging/datamodel/data/PendingAttachmentData.java176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/com/android/messaging/datamodel/data/PendingAttachmentData.java b/src/com/android/messaging/datamodel/data/PendingAttachmentData.java
new file mode 100644
index 0000000..5e079f8
--- /dev/null
+++ b/src/com/android/messaging/datamodel/data/PendingAttachmentData.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015 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.messaging.datamodel.data;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.annotation.NonNull;
+
+import com.android.messaging.util.Assert;
+import com.android.messaging.util.ContentType;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.SafeAsyncTask;
+import com.android.messaging.util.UriUtil;
+
+/**
+ * Represents a "pending" message part that acts as a placeholder for the actual attachment being
+ * loaded. It handles the task to load and persist the attachment from a Uri to local scratch
+ * folder. This item is not persisted to the database.
+ */
+public class PendingAttachmentData extends MessagePartData {
+ /** The pending state. This is the initial state where we haven't started loading yet */
+ public static final int STATE_PENDING = 0;
+
+ /** The state for when we are currently loading the attachment to the scratch space */
+ public static final int STATE_LOADING = 1;
+
+ /** The attachment has been successfully loaded and no longer pending */
+ public static final int STATE_LOADED = 2;
+
+ /** The attachment failed to load */
+ public static final int STATE_FAILED = 3;
+
+ private static final int LOAD_MEDIA_TIME_LIMIT_MILLIS = 60 * 1000; // 60s
+
+ /** The current state of the pending attachment. Refer to the STATE_* states above */
+ private int mCurrentState;
+
+ /**
+ * Create a new instance of PendingAttachmentData with an output Uri.
+ * @param sourceUri the source Uri of the attachment. The Uri maybe temporary or remote,
+ * so we need to persist it to local storage.
+ */
+ protected PendingAttachmentData(final String caption, final String contentType,
+ @NonNull final Uri sourceUri, final int width, final int height,
+ final boolean onlySingleAttachment) {
+ super(caption, contentType, sourceUri, width, height, onlySingleAttachment);
+ mCurrentState = STATE_PENDING;
+ }
+
+ /**
+ * Creates a pending attachment data that is able to load from the given source uri and
+ * persist the media resource locally in the scratch folder.
+ */
+ public static PendingAttachmentData createPendingAttachmentData(final String contentType,
+ final Uri sourceUri) {
+ return createPendingAttachmentData(null, contentType, sourceUri, UNSPECIFIED_SIZE,
+ UNSPECIFIED_SIZE);
+ }
+
+ public static PendingAttachmentData createPendingAttachmentData(final String caption,
+ final String contentType, final Uri sourceUri, final int width, final int height) {
+ Assert.isTrue(ContentType.isMediaType(contentType));
+ return new PendingAttachmentData(caption, contentType, sourceUri, width, height,
+ false /*onlySingleAttachment*/);
+ }
+
+ public static PendingAttachmentData createPendingAttachmentData(final String caption,
+ final String contentType, final Uri sourceUri, final int width, final int height,
+ final boolean onlySingleAttachment) {
+ Assert.isTrue(ContentType.isMediaType(contentType));
+ return new PendingAttachmentData(caption, contentType, sourceUri, width, height,
+ onlySingleAttachment);
+ }
+
+ public int getCurrentState() {
+ return mCurrentState;
+ }
+
+ public void loadAttachmentForDraft(final DraftMessageData draftMessageData,
+ final String bindingId) {
+ if (mCurrentState != STATE_PENDING) {
+ return;
+ }
+ mCurrentState = STATE_LOADING;
+
+ // Kick off a SafeAsyncTask to load the content of the media and persist it locally.
+ // Note: we need to persist the media locally even if it's not remote, because we
+ // want to be able to resend the media in case the message failed to send.
+ new SafeAsyncTask<Void, Void, MessagePartData>(LOAD_MEDIA_TIME_LIMIT_MILLIS,
+ true /* cancelExecutionOnTimeout */) {
+ @Override
+ protected MessagePartData doInBackgroundTimed(final Void... params) {
+ final Uri contentUri = getContentUri();
+ final Uri persistedUri = UriUtil.persistContentToScratchSpace(contentUri);
+ if (persistedUri != null) {
+ return MessagePartData.createMediaMessagePart(
+ getText(),
+ getContentType(),
+ persistedUri,
+ getWidth(),
+ getHeight());
+ }
+ return null;
+ }
+
+ @Override
+ protected void onCancelled() {
+ LogUtil.w(LogUtil.BUGLE_TAG, "Timeout while retrieving media");
+ mCurrentState = STATE_FAILED;
+ if (draftMessageData.isBound(bindingId)) {
+ draftMessageData.removePendingAttachment(PendingAttachmentData.this);
+ }
+ }
+
+ @Override
+ protected void onPostExecute(final MessagePartData attachment) {
+ if (attachment != null) {
+ mCurrentState = STATE_LOADED;
+ if (draftMessageData.isBound(bindingId)) {
+ draftMessageData.updatePendingAttachment(attachment,
+ PendingAttachmentData.this);
+ } else {
+ // The draft message data is no longer bound, drop the loaded attachment.
+ attachment.destroyAsync();
+ }
+ } else {
+ // Media load failed. We already logged in doInBackground() so don't need to
+ // do that again.
+ mCurrentState = STATE_FAILED;
+ if (draftMessageData.isBound(bindingId)) {
+ draftMessageData.onPendingAttachmentLoadFailed(PendingAttachmentData.this);
+ draftMessageData.removePendingAttachment(PendingAttachmentData.this);
+ }
+ }
+ }
+ }.executeOnThreadPool();
+ }
+
+ protected PendingAttachmentData(final Parcel in) {
+ super(in);
+ mCurrentState = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(final Parcel out, final int flags) {
+ super.writeToParcel(out, flags);
+ out.writeInt(mCurrentState);
+ }
+
+ public static final Parcelable.Creator<PendingAttachmentData> CREATOR
+ = new Parcelable.Creator<PendingAttachmentData>() {
+ @Override
+ public PendingAttachmentData createFromParcel(final Parcel in) {
+ return new PendingAttachmentData(in);
+ }
+
+ @Override
+ public PendingAttachmentData[] newArray(final int size) {
+ return new PendingAttachmentData[size];
+ }
+ };
+}