1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.datamodel.action; 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Bundle; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Parcel; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Parcelable; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.TextUtils; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModel; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModelException; 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.action.ActionMonitor.ActionExecutedListener; 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil; 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.LinkedList; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.List; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Base class for operations that perform application business logic off the main UI thread while 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * holding a wake lock. 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * . 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Note all derived classes need to provide real implementation of Parcelable (this is abstract) 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic abstract class Action implements Parcelable { 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG; 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Members holding the parameters common to all actions - no action state 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public final String actionKey; 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If derived classes keep their data in actionParameters then parcelable is trivial 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Bundle actionParameters; 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // This does not get written to the parcel 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private final List<Action> mBackgroundActions = new LinkedList<Action>(); 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Process the action locally - runs on action service thread. 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * TODO: Currently, there is no way for this method to indicate failure 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return result to be passed in to {@link ActionExecutedListener#onActionExecuted}. It is 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * also the result passed in to {@link ActionCompletedListener#onActionSucceeded} if 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * there is no background work. 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Object executeAction() { 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Queues up background work ie. {@link #doBackgroundWork} will be called on the 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * background worker thread. 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected void requestBackgroundWork() { 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mBackgroundActions.add(this); 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Queues up background actions for background processing after the current action has 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * completed its processing ({@link #executeAction}, {@link processBackgroundCompletion} 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * or {@link #processBackgroundFailure}) on the Action thread. 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param backgroundAction 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected void requestBackgroundWork(final Action backgroundAction) { 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mBackgroundActions.add(backgroundAction); 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Return flag indicating if any actions have been queued 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean hasBackgroundActions() { 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return !mBackgroundActions.isEmpty(); 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Send queued actions to the background worker provided 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void sendBackgroundActions(final BackgroundWorker worker) { 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd worker.queueBackgroundWork(mBackgroundActions); 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mBackgroundActions.clear(); 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Do work in a long running background worker thread. 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * {@link #requestBackgroundWork} needs to be called for this method to 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * be called. {@link #processBackgroundFailure} will be called on the Action service thread 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * if this method throws {@link DataModelException}. 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return response that is to be passed to {@link #processBackgroundResponse} 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Bundle doBackgroundWork() throws DataModelException { 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Process the success response from the background worker. Runs on action service thread. 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param response the response returned by {@link #doBackgroundWork} 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return result to be passed in to {@link ActionCompletedListener#onActionSucceeded} 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Object processBackgroundResponse(final Bundle response) { 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Called in case of failures when sending background actions. Runs on action service thread 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return result to be passed in to {@link ActionCompletedListener#onActionFailed} 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Object processBackgroundFailure() { 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Constructor 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Action(final String key) { 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd this.actionKey = key; 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd this.actionParameters = new Bundle(); 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Constructor 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected Action() { 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd this.actionKey = generateUniqueActionKey(getClass().getSimpleName()); 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd this.actionParameters = new Bundle(); 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Queue an action and monitor for processing by the ActionService via the factory helper 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected void start(final ActionMonitor monitor) { 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.registerActionMonitor(this.actionKey, monitor); 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DataModel.startActionService(this); 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Queue an action for processing by the ActionService via the factory helper 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void start() { 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DataModel.startActionService(this); 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Queue an action for delayed processing by the ActionService via the factory helper 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void schedule(final int requestCode, final long delayMs) { 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DataModel.scheduleAction(this, requestCode, delayMs); 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Called when action queues ActionService intent 163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected final void markStart() { 165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.setState(this, ActionMonitor.STATE_CREATED, 166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_QUEUED); 167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Mark the beginning of local action execution 171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected final void markBeginExecute() { 173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.setState(this, ActionMonitor.STATE_QUEUED, 174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_EXECUTING); 175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Mark the end of local action execution - either completes the action or queues 179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * background actions 180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected final void markEndExecute(final Object result) { 182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean hasBackgroundActions = hasBackgroundActions(); 183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.setExecutedState(this, ActionMonitor.STATE_EXECUTING, 184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd hasBackgroundActions, result); 185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!hasBackgroundActions) { 186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.setCompleteState(this, ActionMonitor.STATE_EXECUTING, 187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd result, true); 188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Update action state to indicate that the background worker is starting 193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected final void markBackgroundWorkStarting() { 195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.setState(this, 196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED, 197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION); 198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Update action state to indicate that the background worker has posted its response 202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * (or failure) to the Action service 203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected final void markBackgroundCompletionQueued() { 205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.setState(this, 206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION, 207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_BACKGROUND_COMPLETION_QUEUED); 208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Update action state to indicate the background action failed but is being re-queued for retry 212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected final void markBackgroundWorkQueued() { 214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.setState(this, 215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION, 216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED); 217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Called by ActionService to process a response from the background worker 221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param response the response returned by {@link #doBackgroundWork} 222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected final void processBackgroundWorkResponse(final Bundle response) { 224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.setState(this, 225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_BACKGROUND_COMPLETION_QUEUED, 226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_PROCESSING_BACKGROUND_RESPONSE); 227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Object result = processBackgroundResponse(response); 228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.setCompleteState(this, 229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.STATE_PROCESSING_BACKGROUND_RESPONSE, result, true); 230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Called by ActionService when a background action fails 234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected final void processBackgroundWorkFailure() { 236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Object result = processBackgroundFailure(); 237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ActionMonitor.setCompleteState(this, ActionMonitor.STATE_UNDEFINED, 238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd result, false); 239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final Object sLock = new Object(); 242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static long sActionIdx = System.currentTimeMillis() * 1000; 243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Helper method to generate a unique operation index 246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected static long getActionIdx() { 248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd long idx = 0; 249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd synchronized (sLock) { 250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd idx = ++sActionIdx; 251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return idx; 253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * This helper can be used to generate a unique key used to identify an action. 257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param baseKey - key generated to identify the action parameters 258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return - composite key generated by appending unique index 259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected static String generateUniqueActionKey(final String baseKey) { 261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final StringBuilder key = new StringBuilder(); 262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!TextUtils.isEmpty(baseKey)) { 263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd key.append(baseKey); 264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd key.append(":"); 266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd key.append(getActionIdx()); 267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return key.toString(); 268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Most derived classes use this base implementation (unless they include files handles) 272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public int describeContents() { 275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return 0; 276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Derived classes need to implement writeToParcel (but typically should call this method 280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * to parcel Action member variables before they parcel their member variables). 281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void writeActionToParcel(final Parcel parcel, final int flags) { 283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd parcel.writeString(this.actionKey); 284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd parcel.writeBundle(this.actionParameters); 285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Helper for derived classes to implement parcelable 289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public Action(final Parcel in) { 291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd this.actionKey = in.readString(); 292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Note: Need to set classloader to ensure we can un-parcel classes from this package 293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd this.actionParameters = in.readBundle(Action.class.getClassLoader()); 294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 296