BluetoothOppBatch.java revision 6769b59d715ea98bd72eafcfea9acd2714a887da
1/*
2 * Copyright (c) 2008-2009, Motorola, Inc.
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * - Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * - Neither the name of the Motorola, Inc. nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33package com.android.bluetooth.opp;
34
35import java.io.File;
36import java.util.ArrayList;
37
38import android.content.Context;
39import android.util.Log;
40
41import com.google.android.collect.Lists;
42
43/**
44 * This class stores information about a batch of OPP shares that should be
45 * transferred in one session.
46 */
47/*There are a few cases: 1. create a batch for a single file to send
48 * 2. create a batch for multiple files to send
49 * 3. add additional file(s) to existing batch to send
50 * 4. create a batch for receive single file
51 * 5. add additional file to existing batch to receive (this only happens as the server
52 * session notify more files to receive)
53 * 6. Cancel sending a single file
54 * 7. Cancel sending a file from multiple files (implies cancel the transfer, rest of
55 * the unsent files are also canceled)
56 * 8. Cancel receiving a single file
57 * 9. Cancel receiving a file (implies cancel the transfer, no additional files will be received)
58 */
59public class BluetoothOppBatch {
60    private static final String TAG = "BtOpp Batch";
61
62    private ArrayList<BluetoothOppShareInfo> mShares;
63
64    public long mTimestamp;
65
66    public int mDirection;
67
68    public String mDestination;
69
70    public int mId;
71
72    public int mStatus;
73
74    private BluetoothOppBatchListener mListener;
75
76    private Context mContext;
77
78    /**
79     * An interface for notifying when BluetoothOppTransferBatch is changed
80     */
81    public interface BluetoothOppBatchListener {
82        /**
83         * Called to notify when a share is added into the batch
84         * @param id , BluetoothOppShareInfo.id
85         */
86        public void onShareAdded(int id);
87
88        /**
89         * Called to notify when a share is deleted from the batch
90         * @param id , BluetoothOppShareInfo.id
91         */
92        public void onShareDeleted(int id);
93
94        /**
95         * Called to notify when the batch is canceled
96         */
97        public void onBatchCanceled();
98    }
99
100    /**
101     * A batch is always created with at least one ShareInfo
102     * @param context, Context
103     * @param info, BluetoothOppShareInfo
104     */
105    public BluetoothOppBatch(Context context, BluetoothOppShareInfo info) {
106        mContext = context;
107        mShares = Lists.newArrayList();
108        mTimestamp = info.mTimestamp;
109        mDirection = info.mDirection;
110        mDestination = info.mDestination;
111        mStatus = Constants.BATCH_STATUS_PENDING;
112        mShares.add(info);
113        if (Constants.LOGVV) {
114            Log.v(TAG, "New Batch created for info " + info.mId);
115        }
116    }
117
118    /**
119     * Add one share into the batch.
120     */
121    /* There are 2 cases: Service scans the databases and it's multiple send
122     * Service receives database update and know additional file should be received
123     */
124
125    public void addShare(BluetoothOppShareInfo info) {
126        mShares.add(info);
127        if (mListener != null) {
128            mListener.onShareAdded(info.mId);
129        }
130    }
131
132    /**
133     * Delete one share from the batch.
134     */
135    /*It should only be called under requirement that cancel one single share, but not to
136     * cancel the whole batch. Currently we assume "cancel" is to cancel whole batch.
137     */
138    //TODO: consider if the batch is running or not
139    public void deleteShare(BluetoothOppShareInfo info) {
140        if (info.mStatus == BluetoothShare.STATUS_RUNNING) {
141            info.mStatus = BluetoothShare.STATUS_CANCELED;
142            if (info.mDirection == BluetoothShare.DIRECTION_INBOUND && info.mFilename != null) {
143                new File(info.mFilename).delete();
144            }
145        }
146
147        if (mListener != null) {
148            mListener.onShareDeleted(info.mId);
149        }
150    }
151
152    /**
153     * Cancel the whole batch.
154     */
155    /* 1) If the batch is running, stop the transfer
156     * 2) Go through mShares list and mark all incomplete share as CANCELED status
157     * 3) update ContentProvider for these canceled transfer
158     */
159    public void cancelBatch() {
160        if (Constants.LOGVV) {
161            Log.v(TAG, "batch " + this.mId + " is canceled");
162        }
163        if (mListener != null) {
164            mListener.onBatchCanceled();
165        }
166        //TODO investigate if below code is redundant
167        for (int i = mShares.size() - 1; i >= 0; i--) {
168            BluetoothOppShareInfo info = mShares.get(i);
169
170            if (info.mStatus < 200) {
171                if (info.mDirection == BluetoothShare.DIRECTION_INBOUND && info.mFilename != null) {
172                    new File(info.mFilename).delete();
173                }
174                if (Constants.LOGVV) {
175                    Log.v(TAG, "Cancel batch for info " + info.mId);
176                }
177
178                Constants.updateShareStatus(mContext, info.mId, BluetoothShare.STATUS_CANCELED);
179            }
180        }
181        mShares.clear();
182    }
183
184    /** check if a specific share is in this batch */
185    public boolean hasShare(BluetoothOppShareInfo info) {
186        return mShares.contains(info);
187    }
188
189    /** if this batch is empty */
190    public boolean isEmpty() {
191        return (mShares.size() == 0);
192    }
193
194    /**
195     * Get the running status of the batch
196     * @return
197     */
198    public boolean isRunning() {
199        return (mStatus == Constants.BATCH_STATUS_RUNNING);
200    }
201
202    /** register a listener for the batch change */
203    public void registerListern(BluetoothOppBatchListener listener) {
204        mListener = listener;
205    }
206
207    /**
208     * Get the first pending ShareInfo of the batch
209     * @return BluetoothOppShareInfo, for the first pending share, or null if
210     *         none exists
211     */
212    public BluetoothOppShareInfo getPendingShare() {
213        for (int i = 0; i < mShares.size(); i++) {
214            BluetoothOppShareInfo share = mShares.get(i);
215            if (share.mStatus == BluetoothShare.STATUS_PENDING) {
216                return share;
217            }
218        }
219        return null;
220    }
221}
222